read
is defined in the Prelude as
read :: (Read a) => String -> a
and can be used as e.g. read "1" :: Int
.
Now a function
readOne :: (Read a) => [String] -> (a, [String])
readOne (x:xs) = (read x,xs)
used with readOne ["1","foo"]
results (as expected) in the error
Ambiguous type variable 'a' in the constraint:
'Read a' arising from a use of 'readOne' at :1:0-18
Probable fix: add a type signature that fixes these type variable(s)
But readOne ["1","foo"] :: Int
doesn't work, while
readOneInt :: [String] -> (Int, [String])
readOneInt = readOne
works just fine:
> readOneInt ["1", "foo"]
(1,["foo"])
So: how can I add a type signature to readOne
without defining a new function like readOneInt
?
readOne ["1","foo"] :: Int
doesn't work because readOne
couldn't possibly return an Int
, it always returns a tuple, whose second element is a [String]
. readOne ["1", "foo"] :: (Int, [String])
will work.
Note that you only need to specify the type if it can't be inferred. If you use the result of readOne
in a context where it needs to be an Int
, you can use readOne
without type annotations. Example:
let inc (i, strs) = (i + 1, strs) in
inc (readOne ["1", "foo"])
-- (2, ["foo"])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With