Я работал в Структура и Интерпретация компьютерных программ и завершал упражнения в Haskell. Первые две главы были в порядке (код github), но глава 3 заставляет меня задуматься.
Начнется разговор об управлении состоянием на примере банковского счета. Они определяют функцию make-withdraw
на
(define (make-withdraw balance)
(lambda (amount)
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds")))
чтобы вы могли выполнить следующий код:
(define w1 (make-withdraw 100))
(define w2 (make-withdraw 100))
(w1 50)
50
(w2 70)
30
(w2 40)
"Insufficient funds"
(w1 40)
10
Я не уверен, как я могу подражать этому в Haskell. Сначала я подумал о некоторой простой функции, используя государственную монаду:
import Control.Monad.State
type Cash = Float
type Account = State Cash
withdraw :: Cash -> Account (Either String Cash)
withdraw amount = state makewithdrawal where
makewithdrawal balance = if balance >= amount
then (Right amount, balance - amount)
else (Left "Insufficient funds", balance)
который позволяет мне запускать код
ghci> runState (do { withdraw 50; withdraw 40 }) 100
(Left "Insufficient funds",30.0)
но это делает что-то отличное от кода схемы. В идеале я мог бы запустить что-то вроде
do
w1 <- makeWithdraw 100
w2 <- makeWithdraw 100
x1 <- w1 50
y1 <- w2 70
y2 <- w2 40
x2 <- w1 40
return [x1,y1,y2,x2]
[Right 50,Right 70,Left "Insufficient funds",Right 40]
но я не уверен, как написать функцию makeWithdraw
. Любые советы?