在玩Pointfree时,我看到了一段我似乎无法理解的代码。
:pl map (\x -> x * x) [1..10]
-- map (join (*)) [1..10]
我的主要问题是我不知道join
在这里如何运作。据我所知,它“删除”了一层monadic包装(m (m a)
到m a
)。我认为它归结为像[1..10] >>= (\x -> [x * x])
这样的东西,但我真的不知道如何引入“额外层”。我得到了join x = x >>= id
,但后来我仍然坚持如何“复制”每个值,以便(*)
得到两个参数。这已经困扰了我大约半个小时了,我对自己很生气,因为我觉得我有所有的拼图,但似乎不能把它们放在一起......
P.S。别担心,我不会真正使用这个免费版本,这是纯粹的好奇心,并试图更好地理解Haskell。
答案 0 :(得分:21)
join
正在Monad
使用(->) a
的实例,如Control.Monad.Instances
中所定义。该实例类似于Reader
,但没有明确的包装器。它的定义如下:
instance Monad ((->) a) where
-- return :: b -> (a -> b)
return = const
-- (>>=) :: (a -> b) -> (b -> a -> c) -> (a -> c)
f >>= g = \x -> g (f x) x
如果您现在使用此实例减少join
:
join
(>>= id)
flip (\f g x -> g (f x) x) (\a -> a)
(\f x -> (\a -> a) (f x) x)
(\f x -> f x x)
如您所见,(->) a
的实例使join
成为一个应用两次参数的函数。因此,join (*)
只是\x -> x * x
。