这是类型声明吗?

时间:2018-07-28 09:27:42

标签: haskell

Haskell新手在这里。我正在网上关注这个生成艺术的教程,并遇到了以下代码片段。我运行了它,效果很好。问题是我一点都不明白。

type Generate a = RandT StdGen (ReaderT World Render) a

这是产品类型声明吗?如果可以的话,是否可以像上述那样在括号中组合一组类型?以我的方式来看,它看起来更像是在类型或类似类型中定义的函数。

2 个答案:

答案 0 :(得分:7)

我认为如何解析它并不明显,所以让我们分手吧

type
Generate a
=
RandT
  StdGen
  (ReaderT
    World
    Render)
  a

所以让我们分解一下。第1行是type,表示“我在这里定义类型别名”。类型别名是另一种类型的简写,并且与扩展成的类型完全相同。请注意,data的意思是“我正在定义一个新的数据类型,这就是构造其值的方法”。

第2行说“此类型将称为Generate,并且是具有参数a”,这就是说Generate是某种类型级别事物的函数(在这种情况下,类型,例如IntMaybe Int,而不是Maybe

第4行表示此类型等于类型构造器RandT的某些应用程序。这个东西的种类为* -> (* -> *) -> * -> *,其含义大致为:

  1. 第一个参数是随机数生成器的类型
  2. 第二个参数是Monad
  3. 返回Monad(即第三个参数是Monad内的类型,结果是Monad)

让我们看第二个论点。这是ReaderT的应用,* -> (* -> *) -> * -> *是类型Render的类型级别的东西。第一个参数是您希望能够读取的东西(世界状况)。第二个是您想基于的Monad。在这种情况下,我认为* -> *是您随手建立的艺术作品。就像普通的Haskell中的currying一样,没有第三种,其结果为RandT,这是Generate想要的那种。

读取方式如下:World是一种Monad,它允许使用随机数生成(通过标准生成器),读取{{1}}类型的值并渲染图稿。

答案 1 :(得分:2)

由于到目前为止还没有人提及它,所以您要查找的术语是 monad Translator 。 Monad转换器可让您在现有操作类型的基础上添加各种效果。示例包括ReaderTStateTMaybeT。因此,在您的示例中,您有:

  • Render是描述渲染动作的Monad

  • ReaderT World是monad变压器 ;当应用于monad时,它将生成一个monad,该monad可以读取类型为World的不可变环境。因此,ReaderT World Render是一个描述Render动作的单子,并且还存储了World,该ask可以用asksworld <- ask在这种类型的动作中读取,例如,RandT StdGen

  • StdGen是一种monad转换器,为monad配备了MonadRandom类型的随机数生成器(标准生成器),您可以使用getRandom的方法进行访问:getRandomsgetRandomRgetRandomRsRandT StdGen (ReaderT World Render)。因此,World是一个monad,可以渲染事物,读取StdGen的状态并从dieRoll <- getRandomR (1, 6)中生成随机数,例如type

    < / li>

Generate声明仅将RandT StdGen (ReaderT World Render)定义为a别名,其中一个类型参数Generate表示{的结果类型{1}}个动作。在您看到Generate Foo的任何地方,编译器都会直接替换RandT StdGen (ReaderT World Render) Foo