не удалось сопоставить ожидаемый тип [a0] с фактическим типом IO ()

#haskell #syntax

#haskell #синтаксис

Вопрос:

Что не так в моем коде:

 insertValue file x = 
    if x == "10" then "ok"
    else do putStrLn "Error"; file
  

Ответ №1:

В if..then..else выражении обе ветви должны иметь один и тот же тип.

Одна ветвь:

 "10" :: String
  

Другая ветвь:

 do putStrLn "Error"; file :: IO ??
  

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

Комментарии:

1. Например, значение insertValue «99» «10» должно возвращать «ok». Значение insertValue «99» «5» должно вывести «Ошибка» и вернуть «99».

2. @newuser: В Haskell вы не можете просто выполнить некоторый ввод-вывод (или что-либо еще в монаде), а затем продолжить, как будто вы просто выполнили несколько чистых вычислений. Как только функция коснется IO , она «испорчена» и также должна возвращать IO значение.

3. @newuser: Да, вы можете. Используйте return для преобразования чистого значения в значение, испорченное IO. например, return "ok" и return file .

Ответ №2:

Вам нужно использовать return :: a -> IO a , чтобы «поднять» ваши строки в IO String :

 insertValue file x = 
    if x == "10"
      then return "ok"
      else do putStrLn "Error"
              return file
  

Но вы уверены, что не хотите вызвать putStrLn "ok" (вместо return "ok" ) и вернуть значение Maybe? В противном случае вы возвращаете file or "ok" , и ваш вызывающий абонент никогда не сможет определить, произошла ли ошибка при вызове insertValue файла с именем «ok».

Ответ №3:

«ok» имеет тип «String», в то время как предложение «else» имеет тип «IO ()». В Haskell «if» — это выражение, поэтому они должны совпадать.

Трудно помочь больше, не зная, что вы пытаетесь сделать.