帮助理解pointfree代码

Mic*_*ohl 17 haskell pointfree

在玩Pointfree时,遇到了一段我似乎无法理解的代码.

:pl map (\x -> x * x) [1..10]
-- map (join (*)) [1..10]
Run Code Online (Sandbox Code Playgroud)

我的主要问题是我不知道join这里的工作方式.据我所知,它"移除"了一层monadic包装(m (m a)to m a).我觉得它归结为类似的东西[1..10] >>= (\x -> [x * x]),但我真的不知道如何引入"额外的层".我明白了join x = x >>= id,但是我仍然坚持如何"复制"每个值,以便(*)得到两个参数.这已经困扰了我大约半个小时了,我对自己很生气,因为我觉得我有所有的拼图,但似乎无法将它们放在一起......

PS别担心,我不会真正使用这个免费版本,这是纯粹的好奇心,并试图更好地理解Haskell.

fuz*_*fuz 21

join正在使用Monadfor 的实例(->) 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
Run Code Online (Sandbox Code Playgroud)

如果您现在减少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)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,实例(->) a使得join一个函数可以应用两次参数.因此,join (*)简单来说就是这样\x -> x * x.

  • 我上传了新版Djinn. (8认同)
  • 您也可以从参数化中解决这个问题.在monad`( - >)a`中,`join`的类型为`(( - >)a)(( - >)ab) - >(( - >)ab)`,简化为`(a - > a - > b) - > a - > b`.很明显,只有`join`才能得到一个`b`就可以将'a`提供给函数两次.(当然,除了使用底值). (5认同)
  • @hammar是不是有一个程序可以通过查看类型签名来找出函数唯一合理的定义?(如果可能的话) (2认同)