putStrLn,类型Char不匹配[Char]

1 io haskell functional-programming

我有一个haskell问题.putStrLn应该带一个[Char]或一个String,即使看起来我把它给了编译器,他仍然会抱怨.

*** Expression     : putStrLn line
*** Term           : line
*** Type           : Char
*** Does not match : [Char]
Run Code Online (Sandbox Code Playgroud)

它引用的代码是:

getV::[[(Char,Float)]] -> IO ()
getV [] = putStrLn ""
getV (x:xs) = do line <- getS x
   putStrLn line      <-- Complaining line
   getV xs

getS::[(Char,Float)] -> String
getS [] = ""
getS ((c,f):str) = do a <- "(L" ++ [c] ++")" ++ getS str
    return a
Run Code Online (Sandbox Code Playgroud)

我做了一点剥离它,但它应该是完全相同的行为.getS返回一个String,该字符串是putStrLn的参数.那么问题是什么?:/

ken*_*ytm 11

由于您getS返回a String而不是a IO String,因此无需"提取"纯值<-.

只是用

do
  let line = getS x
  putStrLn line
  getV xs
Run Code Online (Sandbox Code Playgroud)

此外,还有一个mapM功能,你可以

getV xs = mapM (putStrLn.getS) xs
Run Code Online (Sandbox Code Playgroud)

而你getS正在不必要地使用monads.

getS [] = ""
getS ((c,_):str) = "(L" ++ [c] ++ ")" ++ getS str
Run Code Online (Sandbox Code Playgroud)

当然,只能使用内置函数编写它.

getS ps = concatMap (\(c,_) -> "(L" ++ [c] ++ ")") ps
Run Code Online (Sandbox Code Playgroud)

原因你的代码不会失败的line <- getS x线,并line成为Char是因为名单也是一个单子.例如,我们可以将笛卡尔积描述为

cartesian :: [a] -> [b] -> [(a,b)]
cartesian xs ys = do
    x <- xs    -- # Now x is of type 'a', representing any element in xs
    y <- ys    -- # Now y is of type 'b', representing any element in ys
    return (x, y) -- # Return the tuple composed of any elements in xs and ys.
Run Code Online (Sandbox Code Playgroud)

事实上,列表理解是基于列表的这个monadic属性.

cartesian xs ys = [(x, y) | x <- xs, y <- ys]
Run Code Online (Sandbox Code Playgroud)