putStrLn, тип Char не соответствует [Char] - PullRequest
1 голос
/ 04 июня 2010

У меня проблема с haskell. Предполагается, что putStrLn принимает [Char] или String, и хотя мне кажется, что я передаю это г-ну Compiler, он все еще жалуется.

*** Expression     : putStrLn line
*** Term           : line
*** Type           : Char
*** Does not match : [Char]

Код, на который он ссылается, таков:

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

Я немного раздели его, но оно должно быть точно таким же. getS возвращает String, и эта строка является аргументом для putStrLn. Так в чем проблема? : /

1 Ответ

11 голосов
/ 04 июня 2010

Поскольку ваш getS возвращает String, а не IO String, нет необходимости "извлекать" чистое значение с помощью <-.

Просто используйте

do
  let line = getS x
  putStrLn line
  getV xs

Также есть функция mapM , которую вы можете

getV xs = mapM (putStrLn.getS) xs

и ваш getS использует монады без необходимости.

getS [] = ""
getS ((c,_):str) = "(L" ++ [c] ++ ")" ++ getS str

Конечно, написать его можно только с помощью встроенных функций.

getS ps = concatMap (\(c,_) -> "(L" ++ [c] ++ ")") ps

Причина, по которой ваш код не приводит к сбою в строке line <- getS x и line становится Char, заключается в том, что List также является монадой. Например, мы можем написать декартово произведение как

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.

На самом деле, понимание списка основано на этом монадическом свойстве списка.

cartesian xs ys = [(x, y) | x <- xs, y <- ys]
...