【问题标题】:Haskell beginner order functionHaskell初学者订单功能
【发布时间】:2013-11-25 15:09:50
【问题描述】:

我的代码:

isOrdered :: (a -> a -> Bool) -> [a] -> Bool
isOrdered mark xs =(head xs) `mark`(head(tail xs)) 

编译完美,但当我尝试调用它时

isOrdered < [1,2,3]

我收到一个错误:

Couldn't match expected type `(a0 -> a0 -> Bool) -> [a0] -> Bool'
            with actual type `[t0]'
In the second argument of `(<)', namely `[1, 2, 3]'
In the expression: isOrdered < [1, 2, 3]
In an equation for `it': it = isOrdered < [1, 2, 3]

我在这里错过了什么?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    由于&lt; 是中缀,你必须用括号括起来。这会将其转换为前缀。

    1 < 2 ==> (<) 1 2
    1 + 5 ==> (+) 1 5
    

    那么你的代码就变成了

    isOrdered (<) [1, 2, 3]
    

    这实际上是更一般的切片概念的一部分。您可以将中缀运算符完全转换为带括号的前缀,或者像这样部分应用它

    \x -> x + 1 ===> (+1)
    \x -> 2 ^ x ===> (2^)
    

    这有点像梨形的唯一地方是-。由于-是Haskell语言定义的超特殊前缀运算符,你不能做(-2),因为不清楚这是一个部分还是一个数字。 Haskell选择一个数字,但是如果你想要一个部分,有一个函数subtract

    \x -> x - 2 ==> subtract 2
    

    【讨论】:

    • 伙计,一元 - 是一个丑陋的黑客。我个人不介意将否定写成0 - x
    【解决方案2】:

    这行得通:

    isOrdered (<) [1,2,3]
    

    但不知道为什么。这是一个普遍的事情:

    Prelude> :type <
    <interactive>:1:1: parse error on input `<'
    Prelude> :type (<)
    (<) :: Ord a => a -> a -> Bool
    

    我相信其他人会解释的。

    【讨论】:

      【解决方案3】:

      将运算符传递给更高级别的函数时,必须用括号括起来:

      isOrdered (<) [1, 2, 3]
      

      您还必须对部分应用的运算符执行此操作

      map (== 2) [1, 2, 3]
      

      【讨论】:

        【解决方案4】:

        这不是您问题的答案,而只是一个风格提示:惯用的 Haskell 代码应该使用模式匹配而不是 head/tail。静态模式匹配可确保您不会意外尝试访问不存在的元素。

        使用模式匹配编写函数的方式是:

        isOrdered :: (a -> a -> Bool) -> [a] -> Maybe Bool
        isOrdered mark (x:y:_) = Just (x `mark` y)
        isOrdered _    _       = Nothing
        

        请注意,当列表不包含两个元素并将结果包装在 Maybe 中时,我已经包含了一个案例。这会通过强制您处理这种情况来防止运行时错误。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-12-21
          • 1970-01-01
          • 2022-12-09
          • 2017-06-27
          • 1970-01-01
          相关资源
          最近更新 更多