关于haskell组合的错误
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于haskell组合的错误相关的知识,希望对你有一定的参考价值。
我写了一个函数:
inita xs = reverse . (drop 1) (reverse xs)
我认为它等于:
inita xs = reverse ( (drop 1) (reverse xs) )
但我有错误:
Couldn't match expected type ‘a -> [a1]’ with actual type ‘[a2]’
Relevant bindings include
xs :: [a2] (bound at ch2.hs:1:7)
init1 :: [a2] -> a -> [a1] (bound at ch2.hs:1:1)
Possible cause: ‘drop’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘(drop 1) (reverse xs)’
In the expression: reverse . (drop 1) (reverse xs)
Failed, modules loaded: none.
那组成表达有什么问题呢?
答案
reverse ( (drop 1) (reverse xs) )
等于(reverse . drop 1) (reverse xs)
。但这不是reverse . (drop 1) (reverse xs)
被解析的原因,因为中缀运算符的优先级低于函数应用程序。出于这个原因,它实际解析的是reverse . ((drop 1) (reverse xs))
,但这没有任何意义(即不进行类型检查),因为(drop 1) (reverse xs)
不是一个函数而是一个列表。
编写这样一个函数的首选方法是
inita xs = reverse . drop 1 $ reverse xs
在这里,我用低优先级$
运算符替换了高优先级普通函数应用程序(除了应用函数之外什么都不做,但由于优先级低,它实际上是正确的组合函数)。
实际上,你不需要那个,因为你最后只传入一次xs
。所以你也可以将reverse
作为组合链的一部分:
inita xs = reverse . drop 1 . reverse $ xs
......可以简单地将η减少到
inita = reverse . drop 1 . reverse
另一答案
不,运算符的优先级低于函数,因此这意味着您的表达式:
inita xs = reverse . (drop 1) (reverse xs)
等于:
inita xs = (reverse) . ((drop 1) (reverse xs))
或者以更规范的形式:
inita xs = (.) (reverse) ((drop 1) (reverse xs))
现在(.)
被定义为:
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x)
所以在这个背景下,f = reverse
和g = ((drop 1) (reverse xs))
,所以我们基本上写了:
inita xs = x -> reverse ((drop 1) (reverse xs) x)
或者我们可以将x
参数移动到函数的头部:
inita xs x = reverse ((drop 1) (reverse xs) x)
所以你在重写时错过了x
。我们可以将代码重写为:
inita = (reverse .) . drop 1 . reverse
以来:
inita xs = (.) reverse ((drop 1) (reverse xs))
-> inita xs = ((.) reverse) ((drop 1) (reverse xs))
-> inita xs = ((.) reverse) ((.) (drop 1) reverse xs)
-> inita = ((.) reverse) . ((.) (drop 1) reverse)
-> inita = ((.) reverse) . (drop 1 . reverse)
-> inita = ((.) reverse) . drop 1 . reverse
-> inita = (reverse .) . (drop 1 . reverse)
以上是关于关于haskell组合的错误的主要内容,如果未能解决你的问题,请参考以下文章