它有点像这样:
> (guess) 50 > (smaller) 25 > (bigger) 37
现在,这种事情(据我所知)在Haskell中完全不可能,从REPL中调用一些修改全局可变状态的函数,然后立即打印结果,因为它违反了不变性原则.因此,所有交互必须存在于IO和/或State monad中.那就是我被困住的地方.
我似乎无法将IO monad和State monad组合在一起,所以我可以获得输入,打印结果和修改状态,所有这些都在同一个函数中.
这是我到目前为止所得到的:
type Bound = (Int,Int) -- left is the lower bound,right is the upper initial :: Bound initial = (1,100) guess :: Bound -> Int guess (l,u) = (l + u) `div` 2 smaller :: State Bound () smaller = do bd@(l,_) <- get let newUpper = max l $pred $guess bd put $(l,newUpper) bigger :: State Bound () bigger = do bd@(_,u) <- get let newLower = min u $succ $guess bd put $(newLower,u)
我现在需要做的就是设计出一条路
>打印初始猜测
>接收要求更小/更大数字的命令
>相应地修改状态
>递归调用函数,以便再次猜测
如何以优雅的方式组合IO和State来实现这一目标?
注意:我知道这可以在不使用状态的情况下实现;但我想让它忠于原作