2013-04-05 3 views
1

Следующий снимок Haskell не будет компилироваться, и я не могу понять, почему.Haskell IO monad и сделайте обозначение

runCompiler :: TC -> IO() 
runCompiler tc = let cp' = cp in 
    do 
     cp' 
     return() 
    where 
    cp = compileProg tc 

Я получаю следующее сообщение об ошибке от GHCi:

Couldn't match expected type `IO a0' with actual type `String' 
    In a stmt of a 'do' block: cp' 
    In the expression: 
     do { cp'; 
      return() } 
    In the expression: 
     let cp' = cp 
     in 
     do { cp'; 
      return() } 

Любые идеи, что нужно сделать, чтобы сделать его компиляции. Я не понимаю, почему он не примет() в качестве конечного значения.

+3

Что такое подпись типа compileProg? – mhwombat

+1

Почему вы связываете 'compileProg tc' как с' cp'', так и с 'cp'? И почему вы используете как 'let', так и' where' в одной и той же функции? Это сбивает с толку. –

+0

Когда я меняю его на ответ ниже, он компилируется. Теперь моя проблема заключается в том, чтобы вывести строку, возвращаемую compileProg. –

ответ

12

При использовании do обозначения: секвенирование два отчета:

do 
    action1 
    action2 

таких же, как action1 >> action2

так >> имеет типа Monad m => m a -> m b -> m b как action1 и action2 должны быть монадическими значениями.

Оказывается ваша compileProg функция имеет тип TC -> String, в то время как компилятор ожидает, что это будет TC -> IO a для некоторого a, так как вы используете его в do нотации.

Вы можете использовать let

do 
    let _ = compileProg tc 
    return() 

, чтобы получить его для компиляции.

Если вы хотите вывести возвращенную строку, вы можете использовать putStrLn или print:

do 
    putStrLn (compileProg tc) 
    return() 

поскольку putStrLn имеет тип String -> IO() вы можете удалить return():

do 
    putStrLn (compileProg tc) 

На самом деле runCompiler может быть написанных просто как

runCompiler :: TC -> IO() 
runCompiler = putStrLn . compileProg 
+0

Что я хочу сделать, это отобразить вывод compileProg на экране. Типичная подпись compileProg - TC -> String. –

+2

@StuartPaton, тогда вы хотите 'putStrLn (compileProc tc)' – drquicksilver

+0

Чтобы прояснить ответ @ lee: каждый оператор в блоке 'do' имеет тип' IO a' (или это может быть привязка 'let'). 'cp'' имеет тип' String', поэтому он не будет вводить проверку. –

Смежные вопросы