loopshaskellio

couldn´t match type 'IO´ with ´[]` inside a do


Haskell newbie here :) . I wan´t to read iteratively an element from IO and, in case is present, delete the element from the list . In other case, repeat the reading till the element entered is in the list. I have the following code :

import Data.List (delete)

main = do
let initialDieRoll = [23,45,98,34]
strength <- askStrength
let dieRollWithoutStrength = removeStrengthFromDieRollLoop strength initialDieRoll
print dieRollWithoutStrength

removeStrengthFromDieRollLoop :: Int -> [Int] -> [Int]
removeStrengthFromDieRollLoop = removeStrengthFromDieRoll

removeStrengthFromDieRoll :: Int -> [Int] -> [Int]
removeStrengthFromDieRoll strength dieRoll = do
if strength `elem` dieRoll then
  delete strength dieRoll
else do
  "Please, choose an element from the initial die roll"
  newStrength <- askStrength
  removeStrengthFromDieRollLoop askStrength dieRoll


askStrength :: IO Int
askStrength = do
putStr "Strength : "
readLn::IO Int

But , when I request the new strength, I'm getting the following error :

Couldn't match type ‘IO’ with ‘[]’
  Expected: [Int]
  Actual: IO Int
In a stmt of a 'do' block: newStrength <- askStrength
In the expression:
do "Please, choose an element from the initial die roll"
   newStrength <- askStrength
   removeStrengthFromDieRollLoop askStrength dieRoll
In a stmt of a 'do' block:
  if strength `elem` dieRoll then
    delete st

What is the best way to proceed ? How can I fix the error, and which is the best way to request for the value looping each time if the value is not inside the initial list ? . Thanks .


Solution

  • Here's some code that compiles. (I have not run it, though)

    removeStrengthFromDieRoll :: Int -> [Int] -> IO [Int]
    removeStrengthFromDieRoll strength dieRoll = do
      if strength `elem` dieRoll then
        return (delete strength dieRoll)
      else do
        putStrLn "Please, choose an element from the initial die roll"
        newStrength <- askStrength
        removeStrengthFromDieRoll newStrength dieRoll
    
    
    askStrength :: IO Int
    askStrength = do
       putStr "Strength : "
       -- You might need hFlush stdout here, I'm not sure.
       readLn :: IO Int
    

    Some key aspects:

    Finally, IO can be tricky at first to grasp from beginners. We all have been there. I'd suggest to following an IO monad tutorial, if you have not yet done so: there should be plenty of them around the 'net.