winterland1989 / magic-haskell

魔力haskell官方网站
295 stars 28 forks source link

复合单子 #47

Open boboyada opened 7 years ago

boboyada commented 7 years ago

知乎中有一文: Haskell中的范畴之函子和自然变换 可作为辅助材料

其中提到: 态射是可以组合的,函子作为范畴之间的态射,那自然也是可以组合的。函子 F 和函子 G 组合后得到一个新函子 H,这三个函子的关系表示为。在Haskell中有如下的形式:

newtype Compose f g a = Compose {getCompose :: f (g a)} deriving (Show)

instance (Functor f, Functor g) => Functor (Compose f g) where fmap k (Compose fga) = Compose $ fmap (fmap k) fga:: 有时为了简化书写,我们也可以用符号:.: 来表示函子的组合操作。

type f :.: g = Compose f g 常用的数据类型State s a的类型构造子State s就是由((->) s)函子和(, s)函子组合得到的函子。 newtype State s a = State { runState :: s -> (a, s) }

instance Functor (State s) where fmap :: (a -> b) -> State s a -> State s b --fmap f st = State $ fmap (fmap f) (runState st) fmap f st = State $ \s -> let (a, s') = runState st s in (f a, s')

请问 1.这里由((->) s)函子和(, s)函子组合得到的函子State s, 如何用Compose f g来表达? 2. fmap k (Compose fga) = Compose $ fmap (fmap k) fga 这里有二次提升,能分别解释一下第一次提升k,与第二次提升?

winterland1989 commented 7 years ago
  1. 代入Compose ((->) s) (, s) 即可得到
newtype Compose ((->) s) (, s) a = Compose { getCompose :: s ->  (a, s) }

所以你可以定义 type State s a = Compose ((->) s) (, s) a ,从而自动获得Functor的实例定义,不过一般不这么写,太麻烦。

  1. 每次 fmap 就是一次提升。