Я работаю над оценщиком контракта для контракта DSL, который я пишу. Контракт DSL основан на документе финансовых комбинаторов Саймона Пейтона Джонса. Я относительно новичок в Хаскеле и монадах, и у меня проблемы с государственной монадой. Как вы можете видеть ниже, evalAll2 вызывается рекурсивно, пока не будет достигнут конец. У меня есть три переменные в записи ContractSt, которые обновляются при вызове evalC, people - количество сторон договора (идентифицируется уникальным int), остаток - сумма денег в договоре, а владелец - лицо, которому принадлежит контракт. Контракт оценивается так:
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