I have two functions:
prop_merge_check :: Ord a => [a] -> [a] -> Bool
prop_merge_check xs ys = length (merge xs ys) == length (sort (xs ++ ys))
prop_unzip_check :: Ord a => [(a,b)] -> Bool
prop_unzip_check xs = length (unzip xs) >= 0
How can I declare the types of function in a function itself?
I tried this way, but it didn't work out for me.
prop_merge_check xs ys = length (merge (xs::[a]) (ys::[a]))
== length (sort ( (xs::[a]) ++ (ys::[a]) ))
prop_unzip_check xs = length (unzip (xs::[(a,b)])) >= 0
This is a side-effect of Haskell's implicit forall's. Haskell automatically adds 'forall's to all type signatures as necessary, these act as "scoping" rules which limit the names to a particular area. Haskell interprets your signature as:
prop_merge_check :: forall a. Ord a => [a] -> [a] -> Bool
prop_merge_check xs ys =
length (merge (xs::forall a. [a]) (ys:: forall a. [a])) == (length (sort ((xs:: forall a. [a]) ++ (ys:: forall a. [a]))))
That is; it sees every a
in every signature as a completely different variable! That's why it can't make the types work properly. This is an annoying and unobvious quirk, but there's a way around it.
If we enable the ScopedTypeVariables
and provide an explicit forall in the type signature we tell Haskell that we want the scope of the type variables to span the whole function body:
{-# LANGUAGE ScopedTypeVariables #-}
-- ^ Put that at the top of your module
prop_merge_check :: forall a. Ord a => [a] -> [a] -> Bool
prop_merge_check xs ys =
length (merge (xs::[a]) (ys::[a])) == (length (sort ((xs::[a]) ++ (ys::[a]))))
This version should compile, because now the a
in all signatures is considered the same. We can quantify more than one type variable at a time:
prop_unzip_check :: forall a b. Ord a => [(a,b)] -> Bool
prop_unzip_check xs = length (unzip (xs::[(a,b)])) >= 0
Unfortunately there's not currently an easy way to do this sort of thing without adding the explicit forall in the top-level signature, but there are a few proposals for changes to this behaviour. They likely won't be coming any time soon though; so I wouldn't hold your breath.
Good luck! You can look up the docs on ScopedTypeVariables and ExistentialQuantification to learn more about this quirk.
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