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

为什么通常使用newtype而不是状态为monad的类型

  •  4
  • akst  · 技术社区  · 10 年前

    几乎所有我见过的例子 State Monad被包裹在一个 newtype .

    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    
    import Control.Monad.State
    import Control.Applicative
    
    data Bazzar 
      = Bazzar {
        valueOne :: Int      
      , valueTwo :: Int      
      }
    
    newtype BazState a = BazState { unBazify :: State Bazzar a } 
      deriving (Functor, Applicative, Monad, MonadState Bazzar)
    

    我不应该只做一个类型别名,有什么理由吗?

    type BazState a = State Bazzar a
    

    我意识到 新类型 是为了区分同一类型数据结构的两种不同用途,例如为现有类型重新实现类型类,或者如果您想区分该类型的使用与正常行为。或实现其他类型类以使用该类

    如果你没有做上面提到的任何事情 新类型 在这种情况下只是不必要的间接?

    1 回复  |  直到 10 年前
        1
  •  3
  •   bheklilr    10 年前

    除了能够为新类型定义实例之外,还可以将其用作库的“封闭构造函数”API。这样,您可以导出一个没有任何构造函数的单一类型,以及充当基元和组合子的函数,这样库的用户就不能构造无效的类型值。这也意味着,如果你足够小心,你可以在不破坏面向外部的API的情况下改变底层结构。尼尔·米切尔就是一个很好的例子, who said in a recent post about modifying the Shake build system to use the Continuation monad :

    Haskell很酷的一点是,我能够完全替换底层Shake Action monad来自 StateT/IO ReaderT/IO ReaderT/ContT/IO ,而不会破坏Shake的任何用户。Haskell允许我生成有效和灵活的抽象。