2

我试图在 Haskell 中写这样的东西:

length . nub . intersect

但它不起作用。

*Main Data.List> :t intersect
intersect :: Eq a => [a] -> [a] -> [a]
*Main Data.List> :t nub
nub :: Eq a => [a] -> [a]
*Main Data.List> :t length
length :: [a] -> Int

根据类型,我的理解是intersect返回一个类型[a]并捐赠给nub,它正好是一个类型[a],然后也返回一个类型[a]length然后最后返回应该是一个Int。它出什么问题了?

4

3 回答 3

6

这里的问题是intersect 需要 2 个参数(在某种意义上)

您可以显式提供参数之一:

> let f a = length . nub . intersect a
> :t f
f :: Eq a => [a] -> [a] -> Int

或者您可以使用一个有趣的小运算符,例如(.:) = (.) . (.)

> let (.:) = (.) . (.)
> :t length .: (nub .: intersect)
length .: (nub .: intersect) :: Eq a => [a] -> [a] -> Int

这是一个不需要括号的版本:

导入数据列表

infixr 9 .:

(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.:) = (.).(.)

f :: Eq a => [a] -> [a] -> Int
f = length .: nub .: intersect
于 2014-09-09T06:50:22.440 回答
4

我想这是基于您上一个问题中的评论,@CarstenKönig 提到了(.) . (.)

首先,length . nub . intersect不能工作。你的类型是:

(.)       ::         (b -> c) -> (a -> b) -> (a -> c)
length    ::         [a] -> Int
nub       :: Eq a => [a] -> [a]
intersect :: Eq a => [a] -> [a] -> [a] ~ [a] -> ([a] -> [a])

如您所见,intersect类型错误,在 的上下文中(.),类型参数b将被替换为([a] -> [a]),这不是 的nub第一个参数的类型。

于 2014-09-09T06:50:44.727 回答
2

我会这样说:首先以“愚蠢”的方式编写代码,然后将其重构为使用(.). 经过一些练习,组合运算符将变得像第二天性。

所以你首先要写:

yourFunction xs ys = length (nub (intersect xs ys))

让你(.)做的是摆脱(语法上)最内层函数的最后一个参数,所有的括号。在这种情况下,该论点是ys

yourFunction xs = length . nub . intersect xs
于 2014-09-09T19:33:42.033 回答