2016-10-28 67 views
0
data S = Sa Int 
type PMO = StateT Int (ErrorT String IO) 

cs :: S -> PMO() 
cs _ = do 
    mem <- get -- (*) 
    return() 

我已经突出显示了带(*)的行。我怀疑为什么可以调用get函数。我知道getState monad的函数,但我无法看到/掌握事实上是否存在这样的monad。我看到返回的类型是PMO,但它只是返回值。它与get有什么共同之处?Haskell和调用函数。

主要是,我有一个命令式语言编程的经验,所以它让我很难理解它。

+0

的[请问这个国家的单子代码工作?](http://stackoverflow.com/questions/31506839/how-does-this-state-monad-code-works) – duplode

+0

('GET'工作起来可能的复制例如'fresh',除了'get'的基本功能只是'\ s - >(s,s)',而'fresh'也会修改状态。) – duplode

回答

4

退房的get类型:

get :: MonadState s m => m s 

而且,由于在cs类型签名你告诉编译器什么m是,get变为:

get :: StateT Int (ErrorT String IO) Int 

这只是一个一元价值,而不是功能。那么名为mem的值是从哪里来的?最终,get提供的值来自runStateT(或execStateTevalStateT)提供的初始状态值。

如果这仍然看起来很神秘,我建议研究邦政府的工作方式。

+0

“因为在类型签名中你告诉编译器什么是cs,get变成:“我无法理解它。你能说更多吗? – Gilgamesz

+1

在get类型中有两个类型变量。 's'是状态值的类型,通常可以是任何事物。 'm'必须是一个具有'MonadState'实例的数据类型。如果没有类型注释,编译器将使用它可以使用的最普通的类型。你的'cs'函数最终会有一个像'cs :: MonadState am => b - > m()'这样的类型,因为编译器肯定只知道两件事:你的'm'有一个'MonadState'实例因为你使用'get'),并且你返回值'()'。 – user2297560

+1

现在,由于您明确地给它一个类型签名(这是顶级定义的良好实践),因此您正在对类型检查器添加其他约束。事实上,你已经确切地告诉了你需要哪个'MonadState'的实例:'StateT Int(ErrorT String IO)'。因此'get'从'MonadState s m => m s'到'StateT Int(ErrorT String IO)Int'。 (即'm = StateT Int(ErrorT String IO)'和's = Int') – user2297560