Using Haskell's "Maybe", type declarations [beginner's question]
I've started experimenting with Haskell and have a problem. qqq is a function that should print one string if called with "Nothing" and print other things if called with "Just something".
The first attempt seems like working:
qqq Nothing = print "There isn't anything to be printed开发者_JS百科."
qqq (Just x) = print "There is something to be printed." >> print x
main :: IO ()
main = qqq (Just 43)
But:
- when I try to make
main = qqq (Nothing)
it fails ("Ambiguous type variable `a0' in the constraint: (Show a0) arising from a use of 'qqq'") - When I want to add type signature if fails:
qqq :: Maybe x => x -> IO ()
->Type constructor 'Maybe' used as a class
-> But isn't it?
qqq :: (Maybe x) -> IO ()
. Now the signature itself looks like succeed. Butmain = qqq (Just 43)
starts failing with that mysterious(Show a0)
error like inmain = qqq (Nothing)
case.
Questions:
- Why calling qqq with
Nothing
is so different than calling withJust 43
? - What is
(Show a0)
? It is mentioned only in error messages. Any attempts to use it lead to something like "Show not in the scope". - What is correct type signature for this? How to make Haskell print type signature it deduced? Expecting something like:
f 0 = 2
f x = (f (x-1)) + 3
main = print get_type_as_string(f)
-- prints "Number -> Number"
The type of qqq
is:
qqq :: Show a => Maybe a -> IO ()
That means that qqq
takes one parameter of type Maybe a
and returns an IO action without a value, with the constraint that a
implements the Show
typeclass. To find out what Show
is, you can use :i Show
in ghci.
Show
is a typeclass which requires that a value of the type can be converted to a string. qqq
has the constraint because print
wants to print out the value (print
has type Show a => a -> IO ()
). Maybe
is not a typeclass but a data type. You can read more about typeclasses here.
You can let GHC deduce the type signature either by typing the function in a .hs file, then loading the file with ghci (ghci Myfile.hs
), and then typing :t qqq
for displaying the type. You can also define the function in the interactive session with let qqq n = case n of { Nothing -> print "abc"; Just x -> print "def" >> print x }
(it looks a bit different because the function definition has to be on one line in ghci, but the meaning is the same).
When main calls qqq
with qqq (Just 43)
, it is clear the concrete type of Maybe a
is a numeric type (ghci defaults to Integer), so qqq
has the concrete type of Maybe Integer -> IO ()
. However, main calls qqq
with qqq Nothing
, a
could be anything (it is ambiguous) and ghci reports an error.
精彩评论