join
被定义为bind
将组合数据结构扁平化为单一结构。
从类型系统的角度来看,(+) 7 :: Num a => a -> a
可以被认为是Functor
, (+) :: Num a => a -> a -> a
可以被认为是Functor
of Functor
,如何获得一些直觉而不是仅仅依赖类型系统?为什么join (+) 7 === 14
?
尽管可以通过手动逐步执行函数绑定过程来获得最终结果,但如果能给出一些直觉那就太好了。
这是来自NICTA https://github.com/tonymorris/course/blob/master/src/Course/Bind.hs练习。
-- | Binds a function on the reader ((->) t).
--
-- >>> ((*) =<< (+10)) 7
-- 119
instance Bind ((->) t) where
(=<<) ::
(a -> ((->) t b))
-> ((->) t a)
-> ((->) t b)
(f =<< a) t =
f (a t) t
-- | Flattens a combined structure to a single structure.
--
-- >>> join (+) 7
-- 14
join ::
Bind f =>
f (f a)
-> f a
join f =
id =<< f
*Course.State> :t join (+)
join (+) :: Num a => a -> a
*Course.State> :t join
join :: Bind f => f (f a) -> f a
*Course.State> :t (+)
(+) :: Num a => a -> a -> a
如何获得一些直觉而不是仅仅依赖类型系统?
我宁愿说依赖类型系统是构建特定类型直觉的好方法。的类型join
is:
join :: Monad m => m (m a) -> m a
专门针对(->) r
, 它成为了:
(r -> (r -> a)) -> (r -> a)
现在让我们尝试定义join
对于函数:
-- join :: (r -> (r -> a)) -> (r -> a)
join f = -- etc.
我们知道结果一定是r -> a
功能:
join f = \x -> -- etc.
然而,我们根本不知道什么是r
and a
类型是,因此我们对此一无所知f :: r -> (r -> a)
and x :: r
。我们的无知意味着我们只能对它们做一件事:通过x
作为一个论点,两者都f
and to f x
:
join f = \x -> f x x
所以,join
for 函数将相同的参数传递两次,因为这是唯一可能的实现。当然,该实现只是一个适当的单子join
因为它遵循单子定律:
join . fmap join = join . join
join . fmap return = id
join . return = id
验证这一点可能是另一个不错的练习。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)