digitToInt,错误的数据类型和未知的异常

时间:2014-05-20 19:48:50

标签: haskell types io

我之前发布了几乎相同的代码,我用甚至不需要的行创建了很多错误。 previous post

现在我带走了类型签名,我的问题减少到了3。 也许现在我可能能够解释我的问题所在。

ghci表示:

C:\Users\MATZE\Desktop\star.hs:8:25:
Couldn't match expected type `IO b0' with actual type `Int'
In the return type of a call of `digitToInt'
In a stmt of a 'do' block: temp <- digitToInt n
In the expression:
  do { temp <- digitToInt n;
       if (((c < 0) && (temp < 6) && (temp > 0))
           || (bs !! c >= temp)) then
           do { return temp }
       else
           do { putStrLn "Ung\252ltige Eingabe";
                .... } }

C:\Users\MATZE\Desktop\star.hs:20:66:
Couldn't match expected type `Int' with actual type `[Char]'
In the second argument of `(!!)', namely `l'
In the first argument of `replicate', namely `(bs !! l)'
In the second argument of `($)', namely
  `replicate (bs !! l) (" *")'

C:\Users\MATZE\Desktop\star.hs:36:17:
Couldn't match type `IO' with `[]'
Expected type: [()]
  Actual type: IO ()
In the return type of a call of `putStrLn'
In a stmt of a 'do' block:
  putStrLn ("#Spieler " ++ show (pl - 1) ++ "hat gewonnen!")
In the expression:
  do { putStrLn ("#Spieler " ++ show (pl - 1) ++ "hat gewonnen!") }

当我尝试加载时:

import Data.Char

board = [5,4,3,2,1]
--getMove :: [Int] -> Int -> IO Int
getMove bs c = do
    n <- getChar
    if isDigit n then do
        temp <- digitToInt n
        if (((c<0) && (temp<6) && (temp > 0))|| (bs!!c >= temp)) then do
            return temp
        else do
            putStrLn "Ungültige Eingabe"
            getMove bs c
    else do
        putStrLn "Ungültige Eingabe"
        getMove bs c

--drawBoard :: [Int] -> Int -> String -> IO String
drawBoard bs l = do
    putStrLn (show ((l + 1)++":" ++ (concat $ replicate (bs!!l) (" *") )))
    if l < 3 then do
        drawBoard bs (l + 1)
    else do
        putStrLn "\n"

--mainloop :: [Int] -> Int -> IO()
mainloop bs pl = do
    line <- (getMove bs (-1))-1

    number <- getMove bs line
    b1s <- take line bs ++ [ ((bs!!line) - number) ] ++ drop (line + 1) bs
    drawBoard b1s 0
    if ((sum b1s) /= 0) then do
        mainloop b1s ((pl `mod` 2) + 1)
    else do
        putStrLn ("#Spieler "++ show(pl -1)++"hat gewonnen!")

--main :: IO()
main = do
    mainloop board 1

为什么digitToInt有问题?

为什么ghci认为“l”是[char]?

最后的例外情况甚至意味着什么。

1 个答案:

答案 0 :(得分:3)

do notation中的箭头会绑定monadic计算的结果,所以

do ...
   temp <- digitToInt n
   ...

希望digitToInt n具有monadic类型,IO a。相反,绑定纯值的方法是使用let

do ...
   let temp = digitToInt n
   ...

第二个错误与l的类型有关,显然推断为String(a.k.a。[Char])。首先,我建议您取消注释您的类型签名,以确保所有内容都具有您认为的类型。在这种情况下,drawBoard的签名应该少一个参数,

drawBoard :: [Int] -> Int -> IO ()

错误的实际原因是括号show ((l + 1)++":"++...不匹配,在此您将(l + 1)与字符串连接起来。你可能想写show (l + 1)++":"++...

第三个错误类似于第一个,你应该写

let b1s = take line (bs ++ [ ((bs!!line) - number) ] ++ drop (line + 1) bs)

而不是使用箭头。

最后,您尝试使用...-1从返回数字的monadic计算中减去。首先需要绑定计算结果,然后减去1.或者您可以使用fmap / liftM来执行此操作。

作为一种风格建议:您的所有代码都存在于IO monad中,而其中大部分代码都不是必须的。例如,您可以将板绘制为String,然后一次打印。