如何解决“无法将期望的类型“ GameTrace b”与实际类型“ t0-> GameTrace b”匹配”

时间:2019-07-17 02:53:15

标签: haskell monads

我要解决的问题是使用Monad创建一个链接列表跟踪,以存储该状态下的水罐,目标,用户输入以及下一个跟踪。

我已经完成了对基本案例的返回和绑定,但是无法弄清楚如何使其适用于递归案例。

import Control.Monad
import Data.Array
import Text.Read

-- Function to run 
jugTraceIO :: [Jug] -> Goal -> IO ()
jugTraceIO jugs goal = playTraceIO (T.jugGame (mkJugArray jugs) goal)

-- Function that create the trace
playTraceIO :: (forall m. MonadGame m => m ()) -> IO ()
playTraceIO game = go game >>= printEnding
  where
    go :: GameTrace () -> IO ()
    go (Pure _) = return ()
    go (Step jugs goal next) = askPlayer jugs goal >>= \req -> go (next req)

-- Function for user input
askPlayer :: Array Int Jug -> Goal -> IO PlayerMsg
askPlayer jugs (Goal i x) =
    printJugs jugs
    >> putStrLn ("Goal: Jug #" ++ show i ++ " has " ++ show x ++ "litres.")
    >> putStrLn "Please enter which jug to transfer from:"
    >> getInt "Please enter which jug to transfer from:"
    >>= \src -> getInt "Please enter which jug to transfer to:"
    >>= \tgt -> return (FromTo src tgt)

-- Helper Functions    
getInt :: String -> IO Int
getInt msg =
    putStrLn msg
    >> getLine
    >>= \inp ->
    case readMaybe inp of
        Nothing -> putStrLn "Sorry, that's not a number."
                    >> getInt msg
        Just i -> return i

printJugs :: Array Int Jug -> IO ()
printJugs jugs = mapM_ print1 (assocs jugs)
    where
        print1 (i, Jug cap amt) = putStrLn ("Jug #" ++ show i
                                            ++ " capacity=" ++ show cap
                                            ++ " amount=" ++ show amt)

mkJugArray :: [Jug] -> Array Int Jug
mkJugArray jugs = listArray (0, length jugs - 1) jugs

-- Data definitions
data PlayerMsg = FromTo Int Int
    deriving (Eq, Show)
data Jug = Jug Integer Integer
    deriving (Eq, Show)
data Goal = Goal Int Integer
    deriving (Eq, Show)
data GameTrace a
    = Pure a
    | Step (Array Int Jug) Goal (PlayerMsg -> GameTrace a)

-- Test Data
jugArr = [Jug 2 0, Jug 3 0, Jug 4 4]
jugs = mkJugArray jugArr
goal = Goal 0 1

-- Monad Instance
instance Monad GameTrace where
    return a = Pure a
    Pure a >>= k = k a
    Step jugs goal next >>= k = (\f -> k (Step jugs goal (next)))

我希望

Step jugs goal next >>= k = (\f -> k (Step jugs goal (next)))

属于类型

GameTrace a -> (a -> GameTrace b) -> GameTrace b

但实际类型是

GameTrace a -> (a -> GameTrace b) -> t0 -> GameTrace b

0 个答案:

没有答案