Haskell新手在这里。我正在网上关注这个生成艺术的教程,并遇到了以下代码片段。我运行了它,效果很好。问题是我一点都不明白。
type Generate a = RandT StdGen (ReaderT World Render) a
这是产品类型声明吗?如果可以的话,是否可以像上述那样在括号中组合一组类型?以我的方式来看,它看起来更像是在类型或类似类型中定义的函数。
答案 0 :(得分:7)
我认为如何解析它并不明显,所以让我们分手吧
type
Generate a
=
RandT
StdGen
(ReaderT
World
Render)
a
所以让我们分解一下。第1行是type
,表示“我在这里定义类型别名”。类型别名是另一种类型的简写,并且与扩展成的类型完全相同。请注意,data
的意思是“我正在定义一个新的数据类型,这就是构造其值的方法”。
第2行说“此类型将称为Generate
,并且是具有参数a
”,这就是说Generate
是某种类型级别事物的函数(在这种情况下,类型,例如Int
或Maybe Int
,而不是Maybe
)
第4行表示此类型等于类型构造器RandT
的某些应用程序。这个东西的种类为* -> (* -> *) -> * -> *
,其含义大致为:
让我们看第二个论点。这是ReaderT
的应用,* -> (* -> *) -> * -> *
是类型Render
的类型级别的东西。第一个参数是您希望能够读取的东西(世界状况)。第二个是您想基于的Monad。在这种情况下,我认为* -> *
是您随手建立的艺术作品。就像普通的Haskell中的currying一样,没有第三种,其结果为RandT
,这是Generate
想要的那种。
读取方式如下:World
是一种Monad,它允许使用随机数生成(通过标准生成器),读取{{1}}类型的值并渲染图稿。
答案 1 :(得分:2)
由于到目前为止还没有人提及它,所以您要查找的术语是 monad Translator 。 Monad转换器可让您在现有操作类型的基础上添加各种效果。示例包括ReaderT
,StateT
和MaybeT
。因此,在您的示例中,您有:
Render
是描述渲染动作的Monad
。
ReaderT World
是monad变压器 ;当应用于monad时,它将生成一个monad,该monad可以读取类型为World
的不可变环境。因此,ReaderT World Render
是一个描述Render
动作的单子,并且还存储了World
,该ask
可以用asks
或world <- ask
在这种类型的动作中读取,例如,RandT StdGen
。
StdGen
是一种monad转换器,为monad配备了MonadRandom
类型的随机数生成器(标准生成器),您可以使用getRandom
的方法进行访问:getRandoms
,getRandomR
,getRandomRs
和RandT StdGen (ReaderT World Render)
。因此,World
是一个monad,可以渲染事物,读取StdGen
的状态并从dieRoll <- getRandomR (1, 6)
中生成随机数,例如type
。
Generate
声明仅将RandT StdGen (ReaderT World Render)
定义为a
的别名,其中一个类型参数Generate
表示{的结果类型{1}}个动作。在您看到Generate Foo
的任何地方,编译器都会直接替换RandT StdGen (ReaderT World Render) Foo
。