Haskell初学者顺序功能

时间:2013-11-25 15:09:50

标签: haskell

我的代码:

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]

我在这里缺少什么?

4 个答案:

答案 0 :(得分:5)

由于<是中缀,因此必须将其包装在parens中。这会将其转换为前缀。

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

然后你的代码变成了

isOrdered (<) [1, 2, 3]

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

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

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

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

答案 1 :(得分:2)

这有效:

isOrdered (<) [1,2,3]

不知道为什么。这是一般性的事情:

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

我相信其他人会解释。

答案 2 :(得分:2)

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

isOrdered (<) [1, 2, 3]

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

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

答案 3 :(得分:0)

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

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

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

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