Weird behaviour GHCi Haskell Compiler - haskell

In a test I'm asked to infer the type of:
let pr = map head.group.sortBy(flip compare)
I've concluded after inferring it myself that the type was:
Ord a => [a] -> [a]
However when doing :t in GHCi it says the type is:
pr :: [()] -> [()]
What is going on?
Also if in GHCi I do:
map head.group.sortBy(flip compare) [1,2,3,4,100,50,30,25,51,70,61]
I get an error:
Couldn't match expected type `a0 -> [b0]' with actual type `[a1]'
In the return type of a call of `sortBy'
Probable cause: `sortBy' is applied to too many arguments
In the second argument of `(.)', namely
`sortBy (flip compare) [1, 2, 3, 4, ....]'
In the second argument of `(.)', namely
`group . sortBy (flip compare) [1, 2, 3, 4, ....]'
However if I do:
sortBy(flip compare) [1,2,3,4,100,50,30,25,51,70,61]
[100,70,61,51,50,30,25,4,3,2,1]
It works just fine. Why is the first expression failing when the second evaluates sortBy just fine with the exact same arguments?

Your first problem is the dreaded combination of the Monomorphism Restriction, GHCi's inability to see your whole program at once, and GHCi's extended defaulting rules.
In a nutshell, Haskell doesn't like to infer types with polymorphic type class constraints (the Ord a => part of your type signature) for top-level bindings that are written as equations that syntactically do not have arguments. pr = map head.group.sortBy(flip compare) falls foul of this rule (it's a function, so semantically it has arguments, but the equation you're using to define it doesn't), so Haskell wants the Ord-constrained a to be something concrete.
If you put this in a source file and compile it (even via GHCi):
import Data.List
pr = map head.group.sortBy(flip compare)
You get outright errors, like:
foo.hs:3:33:
No instance for (Ord b0) arising from a use of `compare'
The type variable `b0' is ambiguous
Possible cause: the monomorphism restriction applied to the following:
pr :: [b0] -> [b0] (bound at foo.hs:3:1)
Probable fix: give these definition(s) an explicit type signature
or use -XNoMonomorphismRestriction
Note: there are several potential instances:
instance Integral a => Ord (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
instance Ord () -- Defined in `GHC.Classes'
instance (Ord a, Ord b) => Ord (a, b) -- Defined in `GHC.Classes'
...plus 22 others
In the first argument of `flip', namely `compare'
In the first argument of `sortBy', namely `(flip compare)'
In the second argument of `(.)', namely `sortBy (flip compare)'
Failed, modules loaded: none.
For some types in particular (notably numeric types) this kind of "ambiguous type variable" error comes up a lot and would be irritating, so Haskell has some defaulting rules. For example, it will assume an ambiguous type variable constrained only by Num should be Integer. Of course, if you use the function anywhere in the same file like so:
import Data.List
pr = map head.group.sortBy(flip compare)
answer = pr [1,2,3,4,100,50,30,25,51,70,61]
then Haskell can take into account. It still refuses to infer a polymorphic type for pr, but in this case pr is only ever used as if it were [Integer] -> [Integer], so it'll give it that type and allow your code to compile, rather than issue the ambiguous type variable error (the Integer itself is also a result of type defaulting).
In GHCi, your code is compiled one statement at a time, so it can't take into account your use of pr to decide what type to give it. It would give you an ambiguous type error except that GHCi has extended defaulting rules, which kick in here to "save the day" and allow your expression to compile. By defaulting the Ord a => a type variable to the unit type (), your declaration can be interpreted as the definition of a function for condensing arbitrary lists of () into [()] (or [] if the input was empty). Thanks GHCi!
You can resolve this in a few of different ways. One is to add an argument to both sides of your definition of pr, like so:
let pr z = map head.group.sortBy(flip compare) $ z
Now the equation defining pr has an argument syntacically (it's type/meaning still has the same number of arguments), the Monomorphism Restriction doesn't kick in, and Haskell is happy to infer a polymorphic type for pr.
Another is to explicitly tell it you don't want to use the Monomorphism Restriction by either adding {-# LANGUAGE NoMonomorphismRestriction #-} to the top of your module, or by using :set -XNomonomorphismRestriction at the GHCi prompt. Then it will again infer the type Ord a => [a] -> [a] for pr.
A third way is to explicitly give the polymorphic type signature for your function:
import Data.List
pr :: Ord a => [a] -> [a]
pr = map head.group.sortBy(flip compare)
Or in GHCi:
> let { pr :: Ord a => [a] -> [a] ; pr = map head.group.sortBy(flip compare) }
Since even with the Monomorphism Restriction in force Haskell is happy for pr to have a polymorphic type, it just won't infer one for it.
The explicit type signature is probably the most common way people avoid this problem in compiled files, because many people consider it good style to always provide type signatures for top level definitions. In GHCi it's pretty annoying, as you can see; I usually turn off the Monomorphism Restriction there.
As for your second problem, I'm afraid this:
map head.group.sortBy(flip compare) [1,2,3,4,100,50,30,25,51,70,61]
is very different from this:
pr [1,2,3,4,100,50,30,25,51,70,61]
When you've got pr defined as a function, pr refers to the whole function map head.group.sortBy(flip compare), so feeding it an argument feeds an argument to that function. But when you write out the whole expression, just sticking a list to the right of it does not pass it as an argument to the whole expression. It's parsed a bit more like this:
(map head) . (group) . (sortBy (flip compare) [1,2,3,4,100,50,30,25,51,70,61])
As you can see, the list is inside the last function in the pipeline; sortBy (flip compare) [1,2,3,4,100,50,30,25,51,70,61] is being used as a function, which will take an argument and feed its output further through the pipeline (to group). That clearly doesn't make sense, and is why you get an error message complaining about too many arguments being given to sortBy; it's not that you have provided too many arguments to sortBy, but rather that you've provided all its arguments and then used it in a position where it would have to be able to take one more.
This can sometimes be surprising until you get used to it, but any alternative is surprising more frequently (you implicitly depended on parsing working this way in your use of map head and sortBy (flip compare)). All you need to do is remember that ordinary function application (by just sticking two expressions next to each other) is always higher precedence than infix operators (like .); whenever you've got an expression mixing infix operators and ordinary application, each normal application chain (groups of non-operator expressions separated only by whitespace) becomes only a single argument as far as the infix operators are concerned (and then precedence/associativity is used to resolve what the arguments of the infix operators are).
To fix it, you need to add parentheses around the composition pipeline before you introduce the argument, like so:
(map head.group.sortBy(flip compare)) [1,2,3,4,100,50,30,25,51,70,61]
Or use $ to put a "wall" between the composition pipeline and the argument, like so:
map head.group.sortBy(flip compare) $ [1,2,3,4,100,50,30,25,51,70,61]
This works because $ is another infix operator, so it forces all the "normal application" sequences to its left and right to be resolved before one can be applied to the other. It's also a very low precedence operator, so it almost always works when there are other infix operators in play as well (like the .). It's quite a common idiom in Haskell to write expressions of the form f . g . h $ a.

You've been bitten by defaulting, where GHCi (interactive GHCi, not GHC compiling something) will put () in any uninstantiated type parameter in certain cases.
I think you've mixed up . and $. Consider your original expression:
map head . group . sortBy(flip compare) [1,2,3,4,100,50,30,25,51,70,61]
That composes the functions map head, group, and sortBy (flip compare) [...]. Unfortunately, sortBy (flip compare) [...] is a list, not a function, so it can't be composed like that. sortBy (flip compare), however, is, and if we compose those functions together and then apply that function to the list, it'll work:
map head . group . sortBy (flip compare) $ [1,2,3,4,100,50,30,25,51,70,61]

Related

Why does functor composition on an empty list return a Show error?

When calling the following, GHCI returns an error:
Ambiguous type variables ‘f0’, ‘b0’ arising from a use of ‘print’ prevents the constraint ‘(Show (f0 b0))’ from being solved.
From what I understand, this is because the type of my Expression is (Num b, Functor f) => [f b] where f is the ambiguous type.
However, the Functor instance of List defines fmap as map, and the definition of map ignores the function argument in case the second argument is [] to simply return []. This should mean that my expression should simply return [] regardless of how many fmap compositions I apply, and a call to show [] should go through. Why is it that I see the error then?
(fmap.fmap) (+1) []
It is true that your function will always return [], but typeclass dispatch (which happens at compile-time, rather than run-time) must be based on the type of the argument to show. The Show instance for [a] requires that Show a also be resolved (instance Show a => Show [a])---since there are many values of type [a] which do contain elements---and since the type of the list elements (all 0 of them) is ambiguous, the Show constraint can't be resolved.
This might lead you to ask why show [] for example does not have the same issue, since [] :: [a]. The answer here is that GHCi has some special Extended Default Rules heuristics, which apply in certain simple cases, in order to make working at the prompt more pleasant. If you :set -XNoExtendedDefaultRules you can see that show [] will have this same behavior. In your case, since the element type of the list is f0 b0 rather than a single type variable, the linked extended defaulting rules do not apply, and so the list element type still contains ambiguous type variables.
You can see that this is the issue by resolving some of the type constraints yourself, say by using -XTypeApplications. Even resolving the Functor constraint is enough to make the normal Haskell type defaulting rules apply again: (fmap.(fmap #[])) (+1) [] does indeed print [] at the GHCi prompt.

How do you use TypeApplications in Haskell?

With -XTypeApplications in GHC 8.0, you can specify types explicitly with # preceding function arguments. What types does it exactly specify, especially when several # are introduced?
If you look at the type of a function
elem :: (Foldable t, Eq a) => a -> t a -> Bool
we see it has two polymorphic variables, t and a. These variables are what the # type applications specify. It seems that variables introduced in the context — where typeclass constraints go — affect order, and hence the first # specifies the t, and the second the a. In functions without context variables
const :: a -> b -> a
the order is more obvious, the a is first and b is second. As Cactus mentioned in a comment above, you can also use explicit foralls to specify the order yourself.
myConst :: forall b a. a -> b -> a
Now the first type application will specify the b and the second the a.
You may run into this problem of needing to specify types particularly if you're using overloaded strings or lists
elem c "abc...xyz" -- What string type is this?
elem c ['a' .. 'z'] -- What list constructor is this?
therefore we use explicit type applications
elem #[] #Char c ['a' .. 'z']
in this case we only have to specify the #[] and say "this is a [] list type constructor" because GHC infers Char from the list elements, so #Char can be omitted here.
If a polymorphic argument GHC is able to infer happens to come first you can leverage -XPartialTypeSignatures which allows you to use _ in type signatures including type application signatures, telling GHC to just infer that [part of the] type, to make things less verbose.
f #_ #[]

How to work around issue with ambiguity when monomorphic restriction turned *on*?

So, learning Haskell, I came across the dreaded monomorphic restriction, soon enough, with the following (in ghci):
Prelude> let f = print.show
Prelude> f 5
<interactive>:3:3:
No instance for (Num ()) arising from the literal `5'
Possible fix: add an instance declaration for (Num ())
In the first argument of `f', namely `5'
In the expression: f 5
In an equation for `it': it = f 5
So there's a bunch of material about this, e.g. here, and it is not so hard to workaround.
I can either add an explicit type signature for f, or I can turn off the monomorphic restriction (with ":set -XNoMonomorphismRestriction" directly in ghci, or in a .ghci file).
There's some discussion about the monomorphic restriction, but it seems like the general advice is that it is ok to turn this off (and I was told that this is actually off by default in newer versions of ghci).
So I turned this off.
But then I came across another issue:
Prelude> :set -XNoMonomorphismRestriction
Prelude> let (a,g) = System.Random.random (System.Random.mkStdGen 4) in a :: Int
<interactive>:4:5:
No instance for (System.Random.Random t0)
arising from the ambiguity check for `g'
The type variable `t0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance System.Random.Random Bool -- Defined in `System.Random'
instance System.Random.Random Foreign.C.Types.CChar
-- Defined in `System.Random'
instance System.Random.Random Foreign.C.Types.CDouble
-- Defined in `System.Random'
...plus 33 others
When checking that `g' has the inferred type `System.Random.StdGen'
Probable cause: the inferred type is ambiguous
In the expression:
let (a, g) = System.Random.random (System.Random.mkStdGen 4)
in a :: Int
In an equation for `it':
it
= let (a, g) = System.Random.random (System.Random.mkStdGen 4)
in a :: Int
This is actually simplified from example code in the 'Real World Haskell' book, which wasn't working for me, and which you can find on this page: http://book.realworldhaskell.org/read/monads.html (it's the Monads chapter, and the getRandom example function, search for 'getRandom' on that page).
If I leave the monomorphic restriction on (or turn it on) then the code works. It also works (with the monomorphic restriction on) if I change it to:
Prelude> let (a,_) = System.Random.random (System.Random.mkStdGen 4) in a :: Int
-106546976
or if I specify the type of 'a' earlier:
Prelude> let (a::Int,g) = System.Random.random (System.Random.mkStdGen 4) in a :: Int
-106546976
but, for this second workaround, I have to turn on the 'scoped type variables' extension (with ":set -XScopedTypeVariables").
The problem is that in this case (problems when monomorphic restriction on) neither of the workarounds seem generally applicable.
For example, maybe I want to write a function that does something like this and works with arbitrary (or multiple) types, and of course in this case I most probably do want to hold on to the new generator state (in 'g').
The question is then: How do I work around this kind of issue, in general, and without specifying the exact type directly?
And, it would also be great (as a Haskell novice) to get more of an idea about exactly what is going on here, and why these issues occur..
When you define
(a,g) = random (mkStdGen 4)
then even if g itself is always of type StdGen, the value of g depends on the type of a, because different types can differ in how much they use the random number generator.
Moreover, when you (hypothetically) use g later, as long as a was polymorphic originally, there is no way to decide which type of a you want to use for calculating g.
So, taken alone, as a polymorphic definition, the above has to be disallowed because g actually is extremely ambiguous and this ambiguity cannot be fixed at the use site.
This is a general kind of problem with let/where bindings that bind several variables in a pattern, and is probably the reason why the ordinary monomorphism restriction treats them even stricter than single variable equations: With a pattern, you cannot even disable the MR by giving a polymorphic type signature.
When you use _ instead, presumably GHC doesn't worry about this ambiguity as long as it doesn't affect the calculation of a. Possibly it could have detected that g is unused in the former version, and treated it similarly, but apparently it doesn't.
As for workarounds without giving unnecessary explicit types, you might instead try replacing let/where by one of the binding methods in Haskell which are always monomorphic. The following all work:
case random (mkStdGen 4) of
(a,g) -> a :: Int
(\(a,g) -> a :: Int) (random (mkStdGen 4))
do (a,g) <- return $ random (mkStdGen 4)
return (a :: Int) -- The result here gets wrapped in the Monad

Haskell function composition confusion

I'm trying to learn haskell and I've been going over chapter 6 and 7 of Learn you a Haskell. Why don't the following two function definitions give the same result? I thought (f . g) x = f (g (x))?
Def 1
let{ t :: Eq x => [x] -> Int; t xs = length( nub xs)}
t [1]
1
Def 2
let t = length . nub
t [1]
<interactive>:78:4:
No instance for (Num ()) arising from the literal `1'
Possible fix: add an instance declaration for (Num ())
In the expression: 1
In the first argument of `t', namely `[1]'
In the expression: t [1]
The problem is with your type signatures and the dreaded monomorphism restriction. You have a type signature in your first version but not in your second; ironically, it would have worked the other way around!
Try this:
λ>let t :: Eq x => [x] -> Int; t = length . nub
λ>t [1]
1
The monomorphism restriction forces things that don't look like functions to have a monomorphic type unless they have an explicit type signature. The type you want for t is polymorphic: note the type variable x. However, with the monomorphism restriction, x gets "defaulted" to (). Check this out:
λ>let t = length . nub
λ>:t t
t :: [()] -> Int
This is very different from the version with the type signature above!
The compiler chooses () for the monomorphic type because of defaulting. Defaulting is just the process Haskell uses to choose a type from a typeclass. All this really means is that, in the repl, Haskell will try using the () type if it encounters an ambiguous type variable in the Show, Eq or Ord classes. Yes, this is basically arbitrary, but it's pretty handy for playing around without having to write type signatures everywhere! Also, the defaulting rules are more conservative in files, so this is basically just something that happens in GHCi.
In fact, defaulting to () seems to mostly be a hack to make printf work correctly in GHCi! It's an obscure Haskell curio, but I'd ignore it in practice.
Apart from including a type signature, you could also just turn the monomorphism restriction off in the repl:
λ>:set -XNoMonomorphismRestriction
This is fine in GHCi, but I would not use it in real modules--instead, make sure to always include a type signature for top-level definitions inside files.
EDIT: Ever since GHC 7.8.1, the monomorphism restriction is turned off by default in GHCi. This means that all this code would work fine with a recent version of GHCi and you do not need to set the flag explicitly. It can still be an issue for values defined in a file with no type signature, however.
This is another instance of the "Dreaded" Monomorphism Restriction which leads GHCi to infer a monomorphic type for the composed function. You can disable it in GHCi with
> :set -XNoMonomorphismRestriction

Specific type inference using uncurry function

I've been playing with the uncurry function in GHCi and I've found something I couldn't quite get at all. When I apply uncurry to the (+) function and bind that to some variable like in the code below, the compiler infers its type to be specific to Integer:
Prelude> let add = uncurry (+)
Prelude> :t add
add :: (Integer, Integer) -> Integer
However, when ask for the type of the following expression I get (what I expect to be) the correct result:
Prelude> :t uncurry (+)
uncurry (+) :: (Num a) => (a, a) -> a
What would cause that? Is it particular to GHCi?
The same applies to let add' = (+).
NOTE: I could not reproduce that using a compiled file.
This has nothing to do with ghci. This is the monomorphism restriction being irritating. If you try to compile the following file:
add = uncurry (+)
main = do
print $ add (1,2 :: Int)
print $ add (1,2 :: Double)
You will get an error. If you expand:
main = do
print $ uncurry (+) (1,2 :: Int)
print $ uncurry (+) (1,2 :: Double)
Everything is fine, as expected. The monomorphism restriction refuses to make something that "looks like a value" (i.e. defined with no arguments on the left-hand side of the equals) typeclass polymorphic, because that would defeat the caching that would normally occur. Eg.
foo :: Integer
foo = expensive computation
bar :: (Num a) => a
bar = expensive computation
foo is guaranteed only to be computed once (well, in GHC at least), whereas bar will be computed every time it is mentioned. The monomorphism restriction seeks to save you from the latter case by defaulting to the former when it looks like that's what you wanted.
If you only use the function once (or always at the same type), type inference will take care of inferring the right type for you. In that case ghci is doing something slightly different by guessing sooner. But using it at two different types shows what is going on.
When in doubt, use a type signature (or turn off the wretched thing with {-# LANGUAGE NoMonomorphismRestriction #-}).
There's magic involved in extended defaulting rules with ghci. Basically, among other things, Num constraints get defaulted to Integer and Floating constraints to Double, when otherwise there would be an error (in this case, due to the evil monomorphism restriction).

Resources