从函数应用到函数组合的 Haskell 类型错误

发布于 2024-09-07 07:12:36 字数 724 浏览 9 评论 0原文

这个问题与antal sz回答的函数组合VS函数应用相关。

你怎么能得到这个?

map has type (a -> b) -> [a] -> [b]
head has type [a] -> a
map head  has type [[a]] -> [a]

为什么以下代码的函数组合存在类型错误?

 test :: [Char] -> Bool
 test xs = not . null xs

 getMiddleInitials :: [String] -> [Char]
 getMiddleInitials middleNames = map head . filter (\mn -> not . null mn) middleNames

但这没有类型错误

getFirstElements :: [[a]] -> [a]
getFirstElements = map head . filter (not . null)

是否必须编写一个点自由函数才能利用函数组合? 我还是不太明白函数组合的用法。

请帮忙。 谢谢。

This question is related to this Function Composition VS Function Application which answered by antal s-z.

How you can get this ?

map has type (a -> b) -> [a] -> [b]
head has type [a] -> a
map head  has type [[a]] -> [a]

Why the following code has type error for function composition ?

 test :: [Char] -> Bool
 test xs = not . null xs

 getMiddleInitials :: [String] -> [Char]
 getMiddleInitials middleNames = map head . filter (\mn -> not . null mn) middleNames

but this does not have type error

getFirstElements :: [[a]] -> [a]
getFirstElements = map head . filter (not . null)

Is it a must to write a point free function in order to utilize the function composition ?
I still not very understand the usage of function composition.

Please help.
Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

猥︴琐丶欲为 2024-09-14 07:12:36

这是因为函数应用 x y 的优先级高于组合 x 。 y

 test :: [Char] -> Bool
 test xs = (not . null) xs
 -- #      ^          ^

 getMiddleInitials :: [String] -> [Char]
 getMiddleInitials middleNames = (map head . filter (\mn -> (not . null) mn)) middleNames
 -- #                            ^                          ^          ^    ^

That's just because function application x y has higher precedence than composition x . y

 test :: [Char] -> Bool
 test xs = (not . null) xs
 -- #      ^          ^

 getMiddleInitials :: [String] -> [Char]
 getMiddleInitials middleNames = (map head . filter (\mn -> (not . null) mn)) middleNames
 -- #                            ^                          ^          ^    ^
枕花眠 2024-09-14 07:12:36

你这里的错误实际上非常简单。如果您还记得我对您上一个问题的回答的最后一部分,对于函数应用,. 运算符的优先级高于除之外的任何运算符。因此,考虑您的示例

test :: [Char] -> Bool
test xs = not . null xs

This is parsed as test xs = not 。 (空xs)。当然,null xs 的类型为 Bool,并且您无法组合布尔值,因此会出现类型错误。因此,你可以让你的例子像这样工作:

test :: [Char] -> Bool
test xs = (not . null) xs

getMiddleInitials :: [String] -> [Char]
getMiddleInitials middleNames =
  (map head . filter (\mn -> (not . null) mn)) middleNames

当然,这样写是不寻常的,但它会工作得很好。

不,除了无点样式之外,函数组合还有其他用途。一个示例是对某些事物使用函数组合(例如,mapfilter 的参数),但指定其余部分。例如,以这个人为的例子为例:

rejectMapping :: (a -> Bool) -> (a -> b) -> [a] -> [b]
rejectMapping p f = map f . filter (not . p)

这部分是无点的(例如,不是 .p,我们省略了最后一个参数),但部分是满点的(的存在pf)。

Your error here is actually really simple. If you remember the last part of my answer to your last question, the . operator has higher precedence than anything except for function application. Thus, consider your example of

test :: [Char] -> Bool
test xs = not . null xs

This is parsed as test xs = not . (null xs). Of course, null xs has type Bool, and you can't compose a boolean, and so you get a type error. Thus, you could make your examples work like so:

test :: [Char] -> Bool
test xs = (not . null) xs

getMiddleInitials :: [String] -> [Char]
getMiddleInitials middleNames =
  (map head . filter (\mn -> (not . null) mn)) middleNames

Of course, writing it this way is unusual, but it would work fine.

And no, there are other uses of function composition besides point-free style. One example is to use function composition for some things (e.g. the argument to map or filter), but specify the rest. For instance, take this contrived example:

rejectMapping :: (a -> Bool) -> (a -> b) -> [a] -> [b]
rejectMapping p f = map f . filter (not . p)

This is partly point-free (not . p, for instance, and we left off the final argument), but partly point-full (the existence of p and f).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文