【问题标题】:Why is newtype commonly used instead of type with the state monad为什么通常使用 newtype 而不是带有 state monad 的 type
【发布时间】:2014-08-23 23:25:51
【问题描述】:

我见过的几乎所有关于 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 不是只是不必要的间接吗?

【问题讨论】:

  • 您不能为类型同义词定义实例。
  • 你确定吗?我可以毫无问题地将type Blah a = [(Int, a)] 输入到ghci 中。哦等等,我只是重读了你说的话,这很公平。
  • 问题是尽管我见过的大多数示例都没有实现任何额外的类型类。我会更新我的问题
  • 它还可以让您的 api 以这样一种方式导出 monad 或其他类型的库,而无需导出它的构造函数,如果您将来需要更改底层类型,它会更容易在不破坏面向外的 API 的情况下这样做。
  • 这是一个很好的观点,我实际上并没有将其视为一个用例,请随意回答问题。

标签: haskell state-monad newtype


【解决方案1】:

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

Haskell 最酷的地方在于,我已经能够完全替换底层的 Shake Action monad 从 StateT/IOReaderT/IOReaderT/ContT/IO,而不会破坏任何 Shake 用户。 Haskell 让我能够产生有效和灵活的抽象。

【讨论】:

    猜你喜欢
    • 2015-10-07
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 2015-07-14
    • 2020-01-16
    • 1970-01-01
    • 2011-10-03
    相关资源
    最近更新 更多