【发布时间】:2019-01-04 18:33:12
【问题描述】:
我正在为我正在编写的合同 DSL 开发合同评估器。合同 DSL 基于 Simon Peyton Jones 金融组合文件。我对 Haskell 和 monads 比较陌生,而且我遇到了 state monad 的问题。正如您在下面看到的,递归调用 evalAll2 直到到达 End。我在记录 ContractSt 中有三个变量,它们在调用 evalC 时更新,people 是合同的参与方数量(由唯一的 int 标识),balance 是合同中的金额,所有者是拥有的人合同。合同的评估如下:
bettingContract :: Contract
bettingContract
= until (Date (2018,12,13))
(cashIn 20 1
(cashIn 20 2
(time (Date (2018,12,15))
(pay 1 2 40 End)
End)
End)
End)
End
c1 = evalAll(bettingContract)
我希望代码做的是输出正在评估的合同,“输出”是基于特定操作生成的消息,并在合同评估后显示 ContractSt 的值。主要问题是我得到:
<interactive>:12:1: error:
* No instance for (Show
(Control.Monad.Trans.State.Lazy.StateT
ContractSt
Data.Functor.Identity.Identity
()))
arising from a use of `print'
当我尝试评估合同时。我知道我必须使用 evalState 来返回最终结果(这是我想要的),并且我不是试图为 show for () 创建一个实例,而是与合同一起返回最终状态,并且输出是我遇到最大困难的地方。
data ContractSt = ContractSt {
people :: [Person], balance :: Money, owner :: Person } deriving (Show)
evalAll :: Contract -> (Contract, OP, State ContractSt ()
evalAll c = evalAll2 c [] initialState
evalAll2 :: Contract -> OP -> State ContractSt () -> (Contract, OP, State
ContractSt ()
evalAll2 c o s
| c == End = (c, o, s)
| otherwise = evalAll2 nc (o ++ no) ns
where
(nc, no,ns) = evalC c
【问题讨论】:
-
这是问题“如何从
State Foo ()获得最终的Foo?”的长格式版本吗?或者是如何在给定函数f :: x -> c的情况下将元组(a,b,x)变成元组(a,b,c)? -
是的更多是后者,我想在一个元组中返回 Contractst 的最终结果,其中包含当前正在评估的合约和输出消息。