我的代码:
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]
我在这里缺少什么?
答案 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
中。这可以通过强制您处理这种情况来防止运行时错误。