2016-02-10 38 views
3

创建状态的情况下在y-taka-23 adaptation of LYAH我发现,大部分片断的第13章必须处理缺乏State构造,例如原来的Haskell代码:弗雷格

randomSt = State random 

被改写为:

randomSt = do 
    gen <- State.get 
    let (x, newGen) = random gen 
    State.put newGen 
    return x 

这当然有它自己的说教优点!但是我想知道是否有另一种方法来创建State的实例。我知道Frege和Haskell之间的这种差异来自于Frege的Control.monad.State模块中的State s a是一种抽象数据类型。是否可以定义从它派生的新的具体数据类型,并使用它的构造函数?

回答

3

难道你不能只写一个聪明的构造函数吗?

state :: (s -> (a, s)) -> State s a 
state f = do 
    s <- State.get 
    let (x, s') = f s 
    State.put s' 
    return x 

写一次(可能在一个库中,您可以下载?),然后在需要的地方使用它。

+0

是的,这个解决方案似乎像Haskell Control.Monad.Trans.State一样模仿'state'函数,如Wikibook [here。](https:/ /en.wikibooks.org/wiki/Haskell/Understanding_monads/State) –

1

事实上,一些特定的状态实例与

State random 

建设也相当考究,而且它在弗雷格是不可能的,因为State数据构建器不能访问。这是不幸的,但它也保护你不要编写依赖于某些实现细节的代码。

例如,我正在为Frege开发一个新的后端,它利用Java lambda并尝试发出类型安全的通用Java代码,并且在做这件事的过程中,结果证明我需要另一个State的表示。因此,在下一个Frege版本中,不再需要一个函数作为参数的构造函数State

尽管发生了这种变化,并且编译器的大部分组件都由状态操作组成,但我并没有因为这个原因而在编译器代码中更改任何单一行。我可以确定我不会伤害别人的代码。大赢!

无论如何,我觉得我们可以在标准库中包含@ jcast的智能状态构造函数。 (我只是重写了一个案例。)

+0

听起来很合理,但我仍然不明白构造函数会如何破坏任何东西。 –

+0

@ libnull-dev由于构造函数揭示了这个状态的实现细节,它与s - >(a,s)是同构的,但正如我试图解释的那样,这不一定是最好的实现。当您 - stdlib使用者 - 知道构造函数时,实现无法以向后兼容的方式更改。 – Ingo

+0

好的,那么这是否意味着'国家'可以有别于'国家'的表示? –