haskell的范畴是hask范畴(haskell的所有类型隶属于hask范畴),所以haskell的所有函子都是自函子。
monad首先是一个函子(自函子)
数学范畴论定义:
unit : x -> m x
join/bind : m m x -> m x
这种定义是数学上的范畴学上定义,函数式语言采用 return(unit)和>>=(join/bind)来表示;
换算关系:
join : : M M a -> M a
join a = a >>= id (这里的a就是 M M a 类型)
同理:
>>= : : M a -> (a -> M b) -> M b
a >>= f = join fmap f a (这里的a仍然是M a类型,一定注意f的类型为 a -> m b类型)
函数式语言用法:
return : : x -> M x
>>= : : M a -> (a -> M b) -> M b
这是haskell语言和数学范畴论的区别
monad的四条定律:
return需要通过上下文推导才能获知类型
1 join . fmap join = join . join
2 join . fmap return = join . return = id
3 return . f = fmap f return (f为普通的映射 A -> B,其中f的入参类型必须和x匹配)
补充第三条 return . f x = fmap f return x ,fmap f M x = M (f x) M就是return
4 join . fmap ( fmap f ) = fmap f . join
haskell中monad对应的四条定律:
第一条;
return x >>= f
= join (fmap f (return x)) -- 根据 (>>=) 的定义
= join (return (f x)) -- 根据公理三
= (join . return) (f x)
= id (f x) -- 根据公理⼆
= f x
第二条;
m >>= return
= join (fmap return m) -- 根据 (>>=) 的定义
= (join . fmap return) m
= id m -- 根据公理⼆
= m
第三条;
(m >>= f) >>= g
= (join (fmap f m)) >>= g -- -- (>>=) 的定义
= join (fmap g (join (fmap f m))) -- -- (>>=) 的定义
= (join .. fmap g) (join (fmap f m))
= (join .. fmap g .. join) (fmap f m)
= (join .. join .. fmap (fmap g)) (fmap f m) -- -- 根据公理四
= (join .. join .. fmap (fmap g) .. fmap f) m
= (join .. join .. fmap (fmap g .. f)) m -- -- 根据函⼦的分配率
= (join .. join .. fmap (\x -> fmap g (f x))) m
如何解释monad就是自函子范畴上的一个幺半群
unit:x->M(x)
join:M(M(x))->M(x)
自函子是一个范畴,元素 Id(恒等变换)。可以去掉 unit 和 join 的参数:
Unit : Id -> M
Join : M × M -> M
Id自函子是幺元,这看起来很像幺半群
join id f = f,
join f id = f,
join (join f g) h = join f (join g h)
而haskell的list,上下文就是 [ ] ,join 重写为concat
网友评论