代码之家  ›  专栏  ›  技术社区  ›  emi

Haskell中状态的函子/应用实例

  •  11
  • emi  · 技术社区  · 16 年前

    在阅读了Wadler关于单子的论文(并浏览了其中的一些章节)之后,我决定更仔细地研究这篇论文,为他描述的每个单子定义函子和应用实例。使用类型同义词

    type M a = State -> (a, State)
    type State = Int
    

    Wadler用来定义state monad,我有以下内容(使用相关名称,以便稍后使用newtype声明来定义它们)。

    fmap' :: (a -> b) -> M a -> M b
    fmap' f m = \st -> let (a, s) = m st in (f a, s)
    
    pure' :: a -> M a
    pure' a = \st -> (a, st)
    
    (<@>) :: M (a -> b) -> M a -> M b
    sf <@> sv = \st -> let (f, st1) = sf st
                           (a, st2) = sv st1
                        in (f a, st2)
    
    return' :: a -> M a
    return' a = pure' a
    
    bind :: M a -> (a -> M b) -> M b
    m `bind` f = \st -> let (a, st1) = m st
                            (b, st2) = f a st1
                         in (b, st2)
    

    当我切换到在newtype声明中使用类型构造函数时,例如。,

    newtype S a = S (State -> (a, State))
    

    一切都崩溃了。一切都只是小小的改变,比如,

    instance Functor S where
     fmap f (S m) = S (\st -> let (a, s) = m st in (f a, s)) 
    
    instance Applicative S where
     pure a = S (\st -> (a, st))
    

    但是,由于lambda表达式隐藏在该类型构造函数中,因此GHC中不会运行任何内容。现在我看到的唯一解决方案是定义一个函数:

    isntThisAnnoying s (S m) = m s
    

    为了将s绑定到'st'并实际返回一个值,例如。,

    fmap f m = S (\st -> let (a, s) = isntThisAnnoying st m in (f a, s))
    

    有没有其他不使用这些辅助功能的方法呢?

    2 回复  |  直到 16 年前
        1
  •  11
  •   Matt Bierner    12 年前

    如果你看 here

    newtype State s a = State { runState :: (s -> (a,s)) }
    

    以便给内在的lambda起个名字。

        2
  •  5
  •   Daniel    16 年前

    newtype newtype S a = S {runState : State -> (a, State)} . 而不是你的 isntThisAnnoying s (S m) runState t s t 与相同 S m .
    你必须使用 newtype 因为类型同义词不能是类型类实例。

    推荐文章