如何在Haskell中使用(.)

如何在Haskell中使用(.),haskell,pointfree,function-composition,combinators,dot-operator,Haskell,Pointfree,Function Composition,Combinators,Dot Operator,我试图在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 根

我试图在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]
返回到
长度,最后返回的应该是
Int
。有什么问题吗?

这里的问题是,
intersect
接受两个参数(在某种意义上)

您可以显式提供其中一个参数:

> let f a = length . nub . intersect a
> :t f
f :: Eq a => [a] -> [a] -> Int
或者你可以使用一个有趣的小操作符,比如
(.:)=(。()

这是一个您不需要parens的版本:

导入数据。列表

infixr 9 .:

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

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

我猜这是基于你上一个问题中的评论,在哪里

首先,
length。核心。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
的第一个参数的类型。

我要说的是:首先以“哑”的方式编写代码,然后重构它以使用
()
。经过一些实践后,合成操作符将变得像第二天性

所以你首先要写:

yourFunction xs ys = length (nub (intersect xs ys))
()
允许您做的是(从语法上)去掉最里面函数的最后一个参数,即所有参数。在本例中,参数为
ys

yourFunction xs = length . nub . intersect xs

实际上,
intersect
返回一种类型的
[a]->[a]
<代码>((length.nub)。)。intersect将执行您想要的操作,但我的理解力太弱,无法回答。另请参见:哦,对了!谢谢它基于前一个问题;)谢谢我现在终于明白了“.”现在意味着什么!
yourFunction xs = length . nub . intersect xs