Reputation: 1281
I have a function which uses Aeson to get data from a json object within a file. The data and function are both defined below.
data Data = Data { date :: String
, temperature :: Int
} deriving (Show, Read, Generic)
data Temperatures = Temperatures { temperatures :: [Data]
} deriving (Show, Generic)
mooStuff :: IO Temperatures
mooStuff = decode <$> getFile
where
getFile = B.readFile "Hello.txt"
The file the function is using contains:
Data {date = "2015-02-28T20:16:12+00:00", temperature = 0}
Data {date = "2015-01-01T21:46:55+00:00", temperature = 2}
Data {date = "2015-04-08T21:46:53+00:00", temperature = 3}
Data {date = "2015-04-09T21:46:01+00:00", temperature = 4}
Data {date = "2015-04-10T21:46:40+00:00", temperature = 5}
Data {date = "2015-04-11T21:46:36+00:00", temperature = 6}
Data {date = "2015-04-12T20:36:25+00:00", temperature = 7}
However I'm getting a type error:
test.hs:37:13:
Couldn't match type ‘Maybe a0’ with ‘Temperatures’
Expected type: B.ByteString -> Temperatures
Actual type: B.ByteString -> Maybe a0
In the first argument of ‘(<$>)’, namely ‘decode’
In the expression: decode <$> getFile
I've been staring at this for hours now, to no avail. Any ideas about where I'm going wrong would be greatly appreciated!
Upvotes: 1
Views: 247
Reputation: 43373
The reason for the error is that decode
does not always succeed. Its type is
decode :: Data a => ByteString -> Maybe a
Correspondingly,
(decode <$>) :: Data a => IO ByteString -> IO (Maybe a)
-- desired type, IO Temperatures, won't unify
The type error message gives you the abstract Maybe a0
as the actual type because it detects the conflict between Maybe
and Temperatures
before it gets anywhere near the point of choosing an appropriate instance for the Data a
in the type of decode
.
Your code needs to account for the possibility that the file delivers its contents but that they don't successfully decode
to Temperatures
.
Something like
do mt <- decode <$> getFile
case mt of
Nothing -> -- handle failure here
Just t -> return t
or if you're happy for decode
failure to trigger an IO
"user error", just
do Just t <- decode <$> getFile
return t
Any way up, there's a failure mode that your code does not address, and that's what's surfacing as a type error.
Upvotes: 11