Haskell ad-hoc polymorphism on values, calculating the length of list of ad-hoc polymorphism - haskell

I am trying to understand one phenomenon from my code below:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Arrow
import Control.Monad
import Data.List
import qualified Data.Map as M
import Data.Function
import Data.Ratio
class (Show a, Eq a) => Bits a where
zer :: a
one :: a
instance Bits Int where
zer = 0
one = 1
instance Bits Bool where
zer = False
one = True
instance Bits Char where
zer = '0'
one = '1'
When I try this:
b = zer:[]
It works perfectly, but when I try:
len = length b
I get this error:
<interactive>:78:8: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘b’
prevents the constraint ‘(Bits a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance [safe] Bits Bool -- Defined at main.hs:18:10
instance [safe] Bits Char -- Defined at main.hs:22:10
instance [safe] Bits Int -- Defined at main.hs:14:10
• In the first argument of ‘length’, namely ‘b’
In the expression: length b
In an equation for ‘it’: it = length b
Can someone explain to me why it is possible to create list from values zer and one, but if I want to calculate length of the list I get an error?

It's perhaps a little easier to understand the meaning of this error in the following example:
roundTrip :: String -> String
roundTrip = show . read
So roundTrip reads a String, and then shows it back into a (presumably identical) String.
But read is a polymorphic function: it parses the input string in a manner that depends on the output type. Parsing an Int is a rather different ask than parsing a Bool!
The elaborator decides which concrete implementation of read to use by looking at the inferred return type of read. But in the expression show . read, the intermediate type could be any type a which implements both Show and Read. How is the compiler supposed to choose an implementation?
You might argue that in your example it doesn't matter because length :: [a] -> Int treats its type argument uniformly. length [zer] is always 1, no matter which instance of Bits you're going through. That sort of situation is difficult for a compiler to detect in general, though, so it's simpler and more predictable to just always reject ambiguous types.
You can fix the issue by giving a concrete type annotation.
> length ([zer] :: [Bool])
1

Related

How does the :: operator syntax work in the context of bounded typeclass?

I'm learning Haskell and trying to understand the reasoning behind it's syntax design at the same time. Most of the syntax is beautiful.
But since :: normally is like a type annotation, How is it that this works:
Input: minBound::Int
Output: -2147483648
There is no separate operator: :: is a type annotation in that example. Perhaps the best way to understand this is to consider this code:
main = print (f minBound)
f :: Int -> Int
f = id
This also prints -2147483648. The use of minBound is inferred to be an Int because it is the parameter to f. Once the type has been inferred, the value for that type is known.
Now, back to:
main = print (minBound :: Int)
This works in the same way, except that minBound is known to be an Int because of the type annotation, rather than for some more complex reason. The :: isn't some binary operation; it just directs the compiler that the expression minBound has the type Int. Once again, since the type is known, the value can be determined from the type class.
:: still means "has type" in that example.
There are two ways you can use :: to write down type information. Type declarations, and inline type annotations. Presumably you've been used to seeing type declarations, as in:
plusOne :: Integer -> Integer
plusOne = (+1)
Here the plusOne :: Integer -> Integer line is a separate declaration about the identifier plusOne, informing the compiler what its type should be. It is then actually defined on the following line in another declaration.
The other way you can use :: is that you can embed type information in the middle of any expression. Any expression can be followed by :: and then a type, and it means the same thing as the expression on its own except with the additional constraint that it must have the given type. For example:
foo = ('a', 2) :: (Char, Integer)
bar = ('a', 2 :: Integer)
Note that for foo I attached the entire expression, so it is very little different from having used a separate foo :: (Char, Integer) declaration. bar is more interesting, since I gave a type annotation for just the 2 but used that within a larger expression (for the whole pair). 2 :: Integer is still an expression for the value 2; :: is not an operator that takes 2 as input and computes some result. Indeed if the 2 were already used in a context that requires it to be an Integer then the :: Integer annotation changes nothing at all. But because 2 is normally polymorphic in Haskell (it could fit into a context requiring an Integer, or a Double, or a Complex Float) the type annotation pins down that the type of this particular expression is Integer.
The use is that it avoids you having to restructure your code to have a separate declaration for the expression you want to attach a type to. To do that with my simple example would have required something like this:
two :: Integer
two = 2
baz = ('a', two)
Which adds a relatively large amount of extra code just to have something to attach :: Integer to. It also means when you're reading bar, you have to go read a whole separate definition to know what the second element of the pair is, instead of it being clearly stated right there.
So now we can answer your direct question. :: has no special or particular meaning with the Bounded type class or with minBound in particular. However it's useful with minBound (and other type class methods) because the whole point of type classes is to have overloaded names that do different things depending on the type. So selecting the type you want is useful!
minBound :: Int is just an expression using the value of minBound under the constraint that this particular time minBound is used as an Int, and so the value is -2147483648. As opposed to minBound :: Char which is '\NUL', or minBound :: Bool which is False.
None of those options mean anything different from using minBound where there was already some context requiring it to be an Int, or Char, or Bool; it's just a very quick and simple way of adding that context if there isn't one already.
It's worth being clear that both forms of :: are not operators as such. There's nothing terribly wrong with informally using the word operator for it, but be aware that "operator" has a specific meaning in Haskell; it refers to symbolic function names like +, *, &&, etc. Operators are first-class citizens of Haskell: we can bind them to variables1 and pass them around. For example I can do:
(|+|) = (+)
x = 1 |+| 2
But you cannot do this with ::. It is "hard-wired" into the language, just as the = symbol used for introducing definitions is, or the module Main ( main ) where syntax for module headers. As such there are lots of things that are true about Haskell operators that are not true about ::, so you need to be careful not to confuse yourself or others when you use the word "operator" informally to include ::.
1 Actually an operator is just a particular kind of variable name that is applied by writing it between two arguments instead of before them. The same function can be bound to operator and ordinary variables, even at the same time.
Just to add another example, with Monads you can play a little like this:
import Control.Monad
anyMonad :: (Monad m) => Int -> m Int
anyMonad x = (pure x) >>= (\x -> pure (x*x)) >>= (\x -> pure (x+2))
$> anyMonad 4 :: [Int]
=> [18]
$> anyMonad 4 :: Either a Int
=> Right 18
$> anyMonad 4 :: Maybe Int
=> Just 18
it's a generic example telling you that the functionality may change with the type, another example:

Cannot understand the error message from a illegal list of tuples

I know this list of tuples doesn't work because the elements of the tuples are not with the same type. But I couldn't understand the error message.
Prelude> [(1,2),("One",2)]
<interactive>:1:3: error:
? Could not deduce (Num [Char]) arising from the literal ‘1’
from the context: Num b
bound by the inferred type of it :: Num b => [([Char], b)]
at <interactive>:1:1-17
? In the expression: 1
In the expression: (1, 2)
In the expression: [(1, 2), ("One", 2)]
Here I think Num[Char]) represents "One". Then what does it means "arising from the literal ‘1’? Does it mean the type of the respective element in the same place has to be integer? And then again, what does it mean from the context: Num b? This make me very confused.
Note that [1, "One"] already triggers the error.
Let's dissecting he error: the key point is
Could not deduce (Num [Char]) arising from the literal ‘1’
This actually means "I need to use 1 :: [Char], since that's the only way the list could type check. However, I don't know how to interpret the literal 1 as a [Char]". (As a reminder, [Char] and String are exactly the same type, and both are the type of string literals such as "One".)
Haskell is a bit peculiar in its handling of numeric literals like 1. There are roughly treated as if the were Integers, the arbitrary-precision integer type, and then immediately transformed into the wanted type using the method fromInteger of typeclass Num.
class Num a where
fromInteger :: Integer -> a
...
In the standard libraries, this class has instances for all numeric types. The user can add others, e.g. for their user-defined numeric types.
A silly programmer could even add an instance for strings!
instance Num [Char] where
fromInteger n = "urk!" ++ show n
This instance is bogus since it can't reasonably define the other methods, but in principle it could be used. With this instance in scope, the original code type checks!
We can test it in GHCi:
> [(1,2),("One",2)]
[("urk!1",2),("One",2)]
Note how Haskell converted the literal as we told it to do.
A a final warning: don't even think to add such an instance to a serious program :) The class Num should be used only for numeric types, and strings are not numeric.

Explicit type conversion?

This is an example function:
import qualified Data.ByteString.Lazy as LAZ
import qualified Data.ByteString.Lazy.Char8 as CHA
import Network.Wreq
makeRequest :: IO (Network.Wreq.Response LAZ.ByteString)
makeRequest = do
res <- get "http://www.example.com"
let resBody = res ^. responseBody :: CHA.ByteString
--Do stuff....
return (res)
I'm struggling to understand the exact purpose of CHA.ByteString in this line:
let resBody = res ^. responseBody :: CHA.ByteString
Is this explicitly stating the type must be CHA.ByteString? Or does it serve another role?
Yes, this is just explicitly stating that the type must be CHA.ByteString. This does (by itself) not incur any sort of conversion, it's just a hint for the compiler (and/or the reader) that res must have this type.
These kinds of local annotations are needed when a value is both produced from a function with polymorphic result, and only consumed by functions with polymorphic argument. A simple example:
f :: Int -> Int
f = fromEnum . toEnum
Here, toEnum converts an integer to a arbitrary enumerable type – could for instance be Char. Whatever type you'd choose, fromEnum would be able to convert it back... trouble is, there is no way to decide which type should be used for the intermediate result!
No instance for (Enum a0) arising from a use of ‘fromEnum’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Integral a => Enum (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance Enum Ordering -- Defined in ‘GHC.Enum’
instance Enum Integer -- Defined in ‘GHC.Enum’
...plus 7 others
In the first argument of ‘(.)’, namely ‘fromEnum’
In the expression: fromEnum . toEnum
In an equation for ‘f’: f = fromEnum . toEnum
For some simple number classes, Haskell has defaults, so e.g. fromIntegral . round will automatically use Integer. But there are no defaults for types like ByteString, so with a polymorphic-result function like responseBody, you either need to pass the result to a monomorphic function that can only accept CHA.ByteString, or you need to add an explicit annotation that this should be the type.
The notation x :: T reads expression x has type T
This may be necessary in the presence of type classes and higher ranked types to enable the compiler to type check the program. For example:
main = print . show . read $ "1234"
is ambiguous, since the compiler cannot know which of the overloaded read functions to use.
In addition, it is possible to narrow the type the compiler would infer. Example:
1 :: Int
Finally, a type signature like this is often used to make the program more readable.

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

read vs map in ghci

I tried the following in ghci 7.6.3
prelude> let m = map
The above works. No errors from GHCi.
But then I tried,
prelude> let r = read
The above code throws a big fat error in GHCi. And this is the error I get,
*Main> let r = read
<interactive>:122:9:
No instance for (Read a0) arising from a use of `read'
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Read IOMode -- Defined in `GHC.IO.IOMode'
instance Read BufferMode -- Defined in `GHC.IO.Handle.Types'
instance Read Newline -- Defined in `GHC.IO.Handle.Types'
...plus 30 others
In the expression: read
In an equation for `r': r = read
And then I tried,
prelude> let r = read :: Read a => String -> a
thinking the type signature might fix things. But then again, I got an error from GHCi. The exact error is as follows,
*Main> let r = read :: Read a => String -> a
<interactive>:123:9:
No instance for (Read a0) arising from an expression type signature
The type variable `a0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
instance Read IOMode -- Defined in `GHC.IO.IOMode'
instance Read BufferMode -- Defined in `GHC.IO.Handle.Types'
instance Read Newline -- Defined in `GHC.IO.Handle.Types'
...plus 30 others
In the expression: read :: Read a => String -> a
In an equation for `r': r = read :: Read a => String -> a
*Main>
Could someone please tell me what is going on?
Thanks.
This is an example of the monomorphism restriction. By default, you aren't allowed to bind polymorphic values like that because it looks like the value of r should only be computed once, but it is actually recomputed every time it is called.
In this case, read is polymorphic because it has an implicit parameter for passing the dictionary for the Read typeclass, so r needs to be recomputed each time. map is monomorphic, because it doesn't have any typeclass restrictions.
If you instead write it as
let r x = read x
it will be allowed.
You can also add a non-polymorphic type signature:
let r = read :: String -> Int
This allows it to compute r a single time for a single instance of Read.
Normal declarations with a type signature are also exempt from the monomorphism restriction, so it you write it like this it will be allowed.
r :: Read a => String -> a
r = read
You can also simply turn off the monomorphism restriction using the -XNoMonomorphismRestriction option or adding {-# LANGUAGE NoMonomorphismRestriction #-} to the top of the file. It is generally considered safe to do this, though it can have a negative performance impact.

Resources