The following code fails with this error.
main.hs:30:13: error:
• Couldn't match type: [[Octopus]]
with: IO a0
Expected: IO a0 -> IO a0
Actual: [[Octopus]] -> [[Octopus]]
• In the first argument of ‘iterate’, namely ‘loopStage’
In the first argument of ‘(!!)’, namely
‘iterate loopStage octopusMatrix’
In a stmt of a 'do' block: iterate loopStage octopusMatrix !! 100
|
30 | iterate loopStage octopusMatrix !! 100
|
module Main where
data Octopus = Octopus {
level :: Int,
hasFlashed :: Int
} deriving (Show)
incrementOctopusEnergyLevelByOne :: Octopus -> Octopus
incrementOctopusEnergyLevelByOne (Octopus level hasFlashed) =
Octopus (level 1) hasFlashed
incrementOctopusListEnergyLevelByOne :: [Octopus] -> [Octopus]
incrementOctopusListEnergyLevelByOne = map incrementOctopusEnergyLevelByOne
increaseAllEnergyLevel :: [[Octopus]] -> [[Octopus]]
increaseAllEnergyLevel = map incrementOctopusListEnergyLevelByOne
loopStage :: [[Octopus]] -> [[Octopus]]
loopStage octopus_matrix = do
increaseAllEnergyLevel octopus_matrix
main = do
contents <- readFile "input.txt"
let fileLines = lines contents
let matrix = parseListOfStringsToMatrixOfIntegers fileLines
let octopusMatrix = convertMatrixToOctopusMatrix matrix
iterate loopStage octopusMatrix !! 100
print octopusMatrix
parseStringToListOfIntegers :: String -> [Int]
parseStringToListOfIntegers string = map (read . (:"")) string :: [Int]
parseListOfStringsToMatrixOfIntegers :: [String] -> [[Int]]
parseListOfStringsToMatrixOfIntegers = map parseStringToListOfIntegers
convertIntToOctopus :: Int -> Octopus
convertIntToOctopus value = Octopus value 0
convertListOfIntsToListOctopus :: [Int] -> [Octopus]
convertListOfIntsToListOctopus = map convertIntToOctopus
convertMatrixToOctopusMatrix :: [[Int]] -> [[Octopus]]
convertMatrixToOctopusMatrix = map convertListOfIntsToListOctopus
My question is, why does the loopStage function expect an IO value? It is clearly marked as [[Octopus]].
I tried removing the iterate, which makes the error message more defined.
main.hs:30:5: error:
• Couldn't match type ‘[]’ with ‘IO’
Expected: IO [Octopus]
Actual: [[Octopus]]
After further debugging, it seems like the error is on the return type of the functions, that it is returning a non IO'able version of [[Octopus]] matrix? This is my first time writing Haskell. I tried wrapping all the return values in IO, but couldn't find a solution
CodePudding user response:
My question is, why does the
loopStage
function expect anIO
value? It is clearly marked as[[Octopus]]
.
Indeed the loopStage
function does not expects IO
. The issue is elsewhere.
Let's focus on these lines.
contents <- readFile "input.txt"
-- ...
iterate loopStage octopusMatrix !! 100
In this do
block, readFile
returns a value inside IO
. Therefore, Haskell infers that iterate loopStage octopusMatrix !! 100
must have type IO something
.
Now, let's look at the iterate
polymorphic type:
iterate :: (a -> a) -> a -> [a]
The result type of
iterate loopStage octopusMatrix !! 100
must then be a
(the element type of [a]
, which is returned by `iterate). Therefore, we must have
iterate loopStage octopusMatrix !! 100 :: a
loopStage :: (a -> a)
octopusMatrix :: a
a = IO something
Hence, we expect
loopStage :: IO something -> IO something
which copes with the actual type of loopStage
:
loopStage :: [[Octopus]] -> [[Octopus]]
Note that the GHC error message is saying exactly this:
Expected: IO a0 -> IO a0
Actual: [[Octopus]] -> [[Octopus]]
This means "You are trying to pass loopStage
which has type [[Octopus]] -> [[Octopus]]
to a function (iterate
) which instead expects a type of the form IO a0 -> IO a0
".
How to fix this? One has to avoid trying to "run" the result of iterate
as if it were an IO action:
let newOctopusMatrix = iterate loopStage octopusMatrix !! 100
print newOctopusMatrix