我见过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
我意识到newtype
的目的是区分同一类型数据结构的两种不同用途,例如为现有类型重新实现类型类,或者如果要区分对类型的使用与正常行为的区别。或者实现其他类型类以使用该类
如果你没有做上面提到的任何事情,在这种情况下是不是使用newtype
只是不必要的间接?
答案 0 :(得分:3)
除了能够为newtype定义实例之外,您还可以将其用作"关闭的构造函数"您的图书馆的API。这样,您可以导出一个没有任何构造函数的单一类型,以及充当基元和组合器的函数,这样您的库的用户就无法构造您的类型的无效值。这也意味着,如果您足够小心,可以在不破坏外向API的情况下更改底层结构。一个很好的例子来自Neil Mitchell,who said in a recent post about modifying the Shake build system to use the Continuation
monad:
关于Haskell的一个很酷的事情是,我已经能够从
Action
,StateT/IO
到ReaderT/IO
完全取代底层的ShakeReaderT/ContT/IO
monad,没有破坏Shake的任何用户。 Haskell允许我产生有效和灵活的抽象。