Can Either be used for a kind of simple polymorphism? - haskell

I tried writing a simple function that takes an Either type (possibly parameterized by two different types) and does one thing if it gets Left and another thing if it gets Right. the following code,
someFunc :: (Show a, Show b) => Either a b -> IO ()
someFunc (Left x) = print $ "Left " ++ show x
someFunc (Right x) = print $ "Right " ++ show x
main = do
someFunc (Left "Test1")
someFunc (Right "Test2")
However, this gives,
Ambiguous type variable `b0' in the constraint:
(Show b0) arising from a use of `someFunc'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of a 'do' expression: someFunc (Left "Test1")
and
Ambiguous type variable `a0' in the constraint:
(Show a0) arising from a use of `someFunc'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: someFunc (Right "Test2")
If I understand correctly, when I call the function with Left x, it is complaining because it doesn't know the type of the Right x variant, and vice-versa. However, this branch of the function is not used. Is there a better way to do this?

You can make this work by explicitly specifying the other type:
main = do
someFunc (Left "Test1" :: Either String ())
someFunc (Right "Test2" :: Either () String)
but I agree with x13n that this probably isn't the best way to do whatever you're trying to do. Note that someFunc is functionally identical to
someFunc :: (Show a) => Bool -> a -> IO ()
someFunc False x = print $ "Left " ++ show x
someFunc True x = print $ "Right " ++ show x
because the only information you derive from the structure of the Either is whether it's a Left or Right. This version also doesn't require you to specify a placeholder type when you use it.

This is a good question, because it made me think about why Haskell behaves this way.
class PseudoArbitrary a where
arb :: a
instance PseudoArbitrary Int where
arb = 4
instance PseudoArbitrary Char where
arb = 'd'
instance PseudoArbitrary Bool where
arb = True
reallyDumbFunc :: (PseudoArbitrary a, PseudoArbitrary b) =>
Either a b -> Either a b
reallyDumbFunc (Left x) = Right arb
reallyDumbFunc (Right x) = Left arb
So check this out. I've made a typeclass PseudoArbitrary, where instances of the typeclass provide a (pseudo-)arbitrary element of their type. Now I have a reallyDumbFunction that takes an Either a b, where both a and b have PseudoArbitrary instances, and if a Left was put in, I produce a Right, with a (pseudo-)arbitrary value of type b in it, and vice versa. So now let's play in ghci:
ghci> reallyDumbFunc (Left 'z')
Ambiguous type variable blah blah blah
ghci> reallyDumbFunc (Left 'z' :: Either Char Char)
Right 'd'
ghci> reallyDumbFunc (Left 'z' :: Either Char Int)
Right 4
Whoa! Even though all I changed was the type of the input, it totally changed the type and value of the output! This is why Haskell cannot resolve the ambiguity by itself: because that would require analyzing your function in complicated ways to make sure you are not doing things like reallyDumbFunc.

Well, that depends heavily on what you are trying to do, doesn't it? As you already found out, in order to use Left constructor, you need to know the type it constructs. And full type requires information on both a and b.
Better way to achieve polymorphism in Haskell is to use type classes. You can easily provide different implementations of "methods" for different instances.
Good comparison of both object-orientation and type classes concepts can be found here.

Related

When I specify x has type a, why does Haskell try to infer it has type a0?

Sometimes I'll specify something's type in a signature as, say, a, and GHC will respond that it can't deduce that its type is a0. Is there a single reason this happens, or a number of different possible reasons? Sometimes I solve it, sometimes not; I'm hoping for a unified theory.
Here's a short example. (To see this code including comments explaining what it's trying to do, see here.)
{-# LANGUAGE MultiParamTypeClasses
, AllowAmbiguousTypes
, FlexibleInstances
, GADTs #-}
type SynthName = String
data Synth format where
Synth :: SynthName -> Synth format
data MessageA format where
MessageA :: String -> MessageA format
data MessageB format where
MessageB :: String -> MessageB format
class (Message format) a where
theMessage :: a -> String
instance (Message format) (MessageA format) where
theMessage (MessageA msg) = msg
instance (Message format) (MessageB format) where
theMessage (MessageB msg) = msg
play :: Message format m => Synth format -> m -> IO ()
play (Synth name) msg =
print $ name ++ " now sounds like " ++ theMessage msg
That produces the following error.
riddles/gadt-forget/closest-to-vivid.hs:38:42: error:
• Could not deduce (Message format0 m)
arising from a use of ‘theMessage’
from the context: Message format m
bound by the type signature for:
play :: forall format m.
Message format m =>
Synth format -> m -> IO ()
at riddles/gadt-forget/closest-to-vivid.hs:36:1-54
The type variable ‘format0’ is ambiguous
Relevant bindings include
msg :: m (bound at riddles/gadt-forget/closest-to-vivid.hs:37:19)
play :: Synth format -> m -> IO ()
(bound at riddles/gadt-forget/closest-to-vivid.hs:37:1)
These potential instances exist:
instance Message format (MessageA format)
-- Defined at riddles/gadt-forget/closest-to-vivid.hs:30:10
instance Message format (MessageB format)
-- Defined at riddles/gadt-forget/closest-to-vivid.hs:32:10
• In the second argument of ‘(++)’, namely ‘theMessage msg’
In the second argument of ‘(++)’, namely
‘" now sounds like " ++ theMessage msg’
In the second argument of ‘($)’, namely
‘name ++ " now sounds like " ++ theMessage msg’
|
38 | print $ name ++ " now sounds like " ++ theMessage msg
Message is a multi-parameter typeclass. In order to determine which instance to use, there needs to be a concrete choice for a and for format. However, the method
theMessage :: a -> String
doesn't even mention format, so we have no way of figuring out which concrete type to use to find an instance of Message. The ambiguous type error you presumably got was about this (but that can be a tricky error message, I don't blame you for just enabling the extension).
The quick fix is to manually specify the format variable using ScopedTypeVariables and TypeApplications (or adding a Proxy format argument to theMessage).
play :: forall format m. Message format m => Synth format -> m -> IO ()
play (Synth name) msg =
print $ name ++ " now sounds like " ++ theMessage #format msg
However, the Message class raises a red flag as a misuse of typeclasses. It's not always bad, but whenever you see a class whose methods all have types like
:: a -> Foo
:: a -> Bar
i.e. they take a single a in contravariant position, it's likely that you don't need a typeclass at all. It's often cleaner to transform the class into a data type, like so:
data Message format = Message { theMessage :: String }
wherein each method becomes a record field. Then concrete types that you instantiated, such as your MessageA, get "demoted" to functions:
messageA :: String -> Message format
messageA msg = Message { theMessage = msg }
Whenever you would have passed an a with a Message constraint, just pass a Message instead. a dissolves into nothingness.
After you do this factoring you might be noticing that a lot of what you have written is sort of tautological and unnecessary. Good! Remove it!
When type checking code involving polymorphic bindings, the type inference engine creates fresh type variables for each use of the binding.
Here's a concrete example:
show () ++ show True
Now, we know that show :: Show a => a -> String. Above the first call to show chooses a ~ (), the second one chooses a ~ Bool. Wait! That looks as a contradiction since () and Bool are distinct types, so they can not be both equal to a. Is that it?
Nah, it is not a contradiction... it looks clear that each call of show can make its choice of a independently. During type inference this is done, roughly, as follows.
For each call we generate a fresh type variable, by renaming universally quantified type variables in the polymorphic type at hand
-- for the first call
show :: Show a0 => a0 -> String
-- for the second call
show :: Show a1 => a1 -> String
Then, we simply pick a0 ~ () and a1 ~ Bool and we are done. The user never realized that this was going on under the hood.
In case there is a type error, however, the freshly generated variables can be reported to the user, revealing a piece of the underlying inference algorithm. For instance
show []
Here, two polymorphic values are used, so we generate fresh variables for both.
[] :: [a0]
show :: Show a1 => a1 -> String
To typecheck, we need a1 ~ [a0], so we end up with (after some context reduction, which does not matter now):
[] :: [a0]
show :: Show a0 => [a0] -> String
Good, we no longer have a1 around. But what about a0? We do not have found any specific value for a0. Indeed, we can not do that, since the code does not contain anything to force that choice: a0 remains an ambiguous type at the end.
This happens because [] can create a list of any type, while show can take a list of any type as input (as long as its element type is showable). But these constraints do not tell us what the type should be!
Concluding, the code is ambiguous, so we have to fix it by telling GHC what type we choose. Any of these would be fine
show ([] :: [Int]) -- choose a0 ~ Int
show ([] :: [Bool]) -- choose a0 ~ Bool
show ([] :: [Char]) -- choose a0 ~ Char
In your code
play :: Message format m => Synth format -> m -> IO ()
play (Synth name) msg =
print $ name ++ " now sounds like " ++ theMessage msg
there is nothing which forces theMessage msg to use the same format which appears in the type of play. It is perhaps "obvious" to you that it should be, but it is not the only possible choice.
Choosing the same format is tricky here since your class has ambiguous types. This could still be used by turning on TypeApplciations and AmbiguousTypes, but something tells me that your design might be wrong, so I am a bit cautious here to suggest a solution. What you are trying to achieve? Why does the type of the Message not mention format in any way?

When are type signatures necessary in Haskell?

Many introductory texts will tell you that in Haskell type signatures are "almost always" optional. Can anybody quantify the "almost" part?
As far as I can tell, the only time you need an explicit signature is to disambiguate type classes. (The canonical example being read . show.) Are there other cases I haven't thought of, or is this it?
(I'm aware that if you go beyond Haskell 2010 there are plenty for exceptions. For example, GHC will never infer rank-N types. But rank-N types are a language extension, not part of the official standard [yet].)
Polymorphic recursion needs type annotations, in general.
f :: (a -> a) -> (a -> b) -> Int -> a -> b
f f1 g n x =
if n == (0 :: Int)
then g x
else f f1 (\z h -> g (h z)) (n-1) x f1
(Credit: Patrick Cousot)
Note how the recursive call looks badly typed (!): it calls itself with five arguments, despite f having only four! Then remember that b can be instantiated with c -> d, which causes an extra argument to appear.
The above contrived example computes
f f1 g n x = g (f1 (f1 (f1 ... (f1 x))))
where f1 is applied n times. Of course, there is a much simpler way to write an equivalent program.
Monomorphism restriction
If you have MonomorphismRestriction enabled, then sometimes you will need to add a type signature to get the most general type:
{-# LANGUAGE MonomorphismRestriction #-}
-- myPrint :: Show a => a -> IO ()
myPrint = print
main = do
myPrint ()
myPrint "hello"
This will fail because myPrint is monomorphic. You would need to uncomment the type signature to make it work, or disable MonomorphismRestriction.
Phantom constraints
When you put a polymorphic value with a constraint into a tuple, the tuple itself becomes polymorphic and has the same constraint:
myValue :: Read a => a
myValue = read "0"
myTuple :: Read a => (a, String)
myTuple = (myValue, "hello")
We know that the constraint affects the first part of the tuple but does not affect the second part. The type system doesn't know that, unfortunately, and will complain if you try to do this:
myString = snd myTuple
Even though intuitively one would expect myString to be just a String, the type checker needs to specialize the type variable a and figure out whether the constraint is actually satisfied. In order to make this expression work, one would need to annotate the type of either snd or myTuple:
myString = snd (myTuple :: ((), String))
In Haskell, as I'm sure you know, types are inferred. In other words, the compiler works out what type you want.
However, in Haskell, there are also polymorphic typeclasses, with functions that act in different ways depending on the return type. Here's an example of the Monad class, though I haven't defined everything:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
fail :: String -> m a
We're given a lot of functions with just type signatures. Our job is to make instance declarations for different types that can be treated as Monads, like Maybe t or [t].
Have a look at this code - it won't work in the way we might expect:
return 7
That's a function from the Monad class, but because there's more than one Monad, we have to specify what return value/type we want, or it automatically becomes an IO Monad. So:
return 7 :: Maybe Int
-- Will return...
Just 7
return 6 :: [Int]
-- Will return...
[6]
This is because [t] and Maybe have both been defined in the Monad type class.
Here's another example, this time from the random typeclass. This code throws an error:
random (mkStdGen 100)
Because random returns something in the Random class, we'll have to define what type we want to return, with a StdGen object tupelo with whatever value we want:
random (mkStdGen 100) :: (Int, StdGen)
-- Returns...
(-3650871090684229393,693699796 2103410263)
random (mkStdGen 100) :: (Bool, StdGen)
-- Returns...
(True,4041414 40692)
This can all be found at learn you a Haskell online, though you'll have to do some long reading. This, I'm pretty much 100% certain, it the only time when types are necessary.

Error while compiling print Either value

I'm trying to compile simple code snippet.
main = (putStrLn . show) (Right 3.423)
Compile results in the following error:
No instance for (Show a0) arising from a use of `show'
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 Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 42 others
In the second argument of `(.)', namely `show'
In the expression: putStrLn . show
In the expression: (putStrLn . show) (Right 3.423)
When i execute same snippet from ghci everything works as expected.
Prelude> let main = (putStrLn . show) (Right 3.423)
Prelude> main
Right 3.423
So the question is what is going on?
The problem is that GHC can't determine what the full type of Right 3.423 is, it can only determine that it has the type Either a Double, and the instance of Show for Either looks like instance (Show a, Show b) => Show (Either a b). Without that extra constraint on Either a Double, GHC doesn't know how to print it.
The reason why it works in interactive mode is because of the dreaded monomorphism restriction, which makes GHCi more aggressive in the defaults it chooses. This can be disabled with :set -XNoMonomorphismRestriction, and that is going to become the default in future versions of GHC since it causes a lot of problems for beginners.
The solution to this problem is to put a type signature on Right 3.423 in your source code, like
main = (putStrLn . show) (Right 3.423 :: Either () Double)
Here I've just used () for a, since we don't care about it anyway and it's the "simplest" type that can be shown. You could put String or Int or Double or whatever you want there, so long as it implements Show.
A tip, putStrLn . show is exactly the definition of print, so you can just do
main = print (Right 3.423 :: Either () Double)
As #ØrjanJohansen points out, this is not the monomorphism restriction, but rather the ExtendedDefaultRules extension that GHCi uses, which essentially does exactly what I did above and shoves () into type variables to make things work in the interactive session.

Specify list type for input

I'm learning Haskell and I've decided to to the H-99 problem set. Naturally, I've become stuck on the first problem!
I have the following code:
module Main where
getLast [] = []
getLast x = x !! ((length x) - 1)
main = do
putStrLn "Enter a list:"
x <- readLn
print (getLast x)
Compiling this code gives the following error:
h-1.hs:8:14:
No instance for (Read a0) arising from a use of `readLn'
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 () -- Defined in `GHC.Read'
instance (Read a, Read b) => Read (a, b) -- Defined in `GHC.Read'
instance (Read a, Read b, Read c) => Read (a, b, c)
-- Defined in `GHC.Read'
...plus 25 others
In a stmt of a 'do' block: x <- readLn
In the expression:
do { putStrLn "Enter a list:";
x <- readLn;
print (getLast x) }
In an equation for `main':
main
= do { putStrLn "Enter a list:";
x <- readLn;
print (getLast x) }
h-1.hs:9:9:
No instance for (Show a0) arising from a use of `print'
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 Show Double -- Defined in `GHC.Float'
instance Show Float -- Defined in `GHC.Float'
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in `GHC.Real'
...plus 26 others
In a stmt of a 'do' block: print (getLast x)
In the expression:
do { putStrLn "Enter a list:";
x <- readLn;
print (getLast x) }
In an equation for `main':
main
= do { putStrLn "Enter a list:";
x <- readLn;
print (getLast x) }
That's a large error, but it seems to me that Haskell isn't sure what the input type will be. That's fine, and completely understandable. However, as this is supposed to work on a list of generics, I'm not sure how to specify that type. I tried this:
x :: [a] <- readLn
...as [a] is the type that Haskell returns for an empty list (found with :t []). This won't compile either.
As I'm a beginner, I know there's a lot I'm missing, but in a basic sense - how can I satisfy Haskell's type system with input code? I'm a Haskell beginner looking for a beginner answer, if that's at all possible. (Also, note that I know there's a better way to do this problem (reverse, head) but this is the way I came up with first, and I'd like to see if I can make it work.)
You can't hope to write something like this which will detect the type of x at run time -- what kind of thing you're reading must be known at compile time. That's why #Sibi's answer uses [Int]. If it can't be deduced, you get a compile time error.
If you want a polymorphic read, you have to construct your own parser which lists the readable types.
maybeDo :: (Monad m) => Maybe a -> (a -> m b) -> m b
maybeDo f Nothing = return ()
maybeDo f (Just x) = f x
main = do
str <- getLine
maybeDo (maybeRead str :: Maybe Int) $ \i ->
putStrLn $ "Got an Int: " ++ show i
maybeDo (maybeRead str :: Maybe String) $ \s ->
putStrLn $ "Got a String: " ++ show s
There are lots of ways to factor out this repetition, but at some point you'll have to list all the types you'll accept.
(An easy way to see the problem is to define a new type MyInt which has the same Read instance as Int -- then how do we know whether read "42" should return an Int or a MyInt?)
This should work:
getLast :: Num a => [a] -> a
getLast [] = 0
getLast x = x !! ((length x) - 1)
main = do
putStrLn "Enter a list:"
x <- readLn :: IO [Int]
print (getLast x)
why return 0 for an empty list, instead of an empty list?
Because it won't typecheck. Because you are returning [] for empty list and for other cases you are returning the element inside the list i.e a. Now since a type is not equal to list, it won't typecheck. A better design would be to catch this type of situation using the Maybe datatype.
Also, because of returning 0, the above function will work only for List of types which have Num instances created for them. You can alleviate that problem using error function.
However, this should work for a generic list, not just a list of Ints
or Numbers, right?
Yes, it should work for a polymorphic list. And you can create a function like getLast which will work for all type of List. But when you want to get input from the user, it should know what type of input you are giving. Because the typechecker won't be able to know whether you meant it as List of Int or List of Double or so on.

"enable_if" in Haskell

How do I write something like the following in Haskell:
showSquare :: (Show a, Num a) => a -> String
showSquare x = "The square of " ++ (show x) ++ " is " ++ (show (x * x))
showSquare :: (Show a, not Num a) => a -> String
showSquare x = "I don't know how to square " ++ (show x)
Basically, something like boost::enable_if in C++.
GHC extensions are ok.
Why would you want this? The typechecker makes sure that you will never call showSquare on something which isn't a Num in the first case. There is no instanceof in Haskell, as everything is typed statically.
It doesn't work for arbitrary types: you can only define your own type class, e.g.
class Mine a where
foo :: a -> String
instance (Num a) => Mine a where
foo x = show x*x
And you can add more instances for other classes, but you won't be able to write just instance Mine a for an arbitrary a. An additional instance (Show a) => ... will also not help, as overlapping instances are also not allowed (the link describes a way to work around it, but it requires quite a bit of additional machinery).
First, giving different type signature to different equations for the same function isn't possible at all. Any function can have only one type, regardless of how much equations it has.
Second, negative constraints does not (would not) have any sound meaning in Haskell. Recall what class constraint mean:
f :: Num a => a -> a -> a
f x y = x + y
Num a in the type of f means that we can apply any class methods of Num type class to values of type a. We are consciously not naming concrete type in order to get generic behavior. Essentially, we are saying "we do not care what a exactly is, but we do know that Num operations are applicable to it". Consequently, we can use Num methods on x and y, but no more than that, that is, we cannot use anything except for Num methods on x and y. This is what type class constraints are and why are they needed. They are specifying generic interface for the function.
Now consider your imaginary not Num a constraint. What information does this statement bring? Well, we know that a should not be Num. However, this information is completely useless for us. Consider:
f :: not Num a => a -> a
f = ???
What can you place instead of ???? Obviously, we know what we cannot place. But except for that this signature has no more information than
f :: a -> a
and the only operation f could be is id (well, undefined is possible too, but that's another story).
Finally consider your example:
showSquare :: (Show a, not Num a) => a -> String
showSquare x = "I don't know how to square " ++ (show x)
I do not give first part of your example intentionally, see the first sentence in my answer. You cannot have different equations with different types. But this function alone is completely useless. You can safely remove not Num a constraint here, and it won't change anything.
The only usage for such negative constrains in statically typed Haskell is producing compile-time errors when you supply, say, Int for not Num a-constrainted variable. But I see no use for this.
If I really, absolutely needed something like this (and I don't believe I ever have), I think this is the simplest approach in Haskell:
class Show a => ShowSquare a where
showSquare :: a -> String
showSquare a = "I don't know how to square " ++ (show a)
instance ShowSquare Int where
showSquare = showSquare'
instance ShowSquare Double where
showSquare = showSquare'
-- add other numeric type instances as necessary
-- make an instance for everything else
instance Show a => ShowSquare a
showSquare' :: (Show a, Num a) => a -> String
showSquare' x = "The square of " ++ (show x) ++ " is " ++ (show (x * x))
This requires overlapping instances, obviously. Some people may complain about the required boilerplate, but it's pretty minimal. 5 or 6 instances would cover most numeric numeric types.
You could probably make something work using ideas from the Advanced Overlap wiki page. Note that technique still requires instances to be listed explicitly, so whether it's better than this is probably a matter of taste.
It's also possible to approach the problem with template haskell, by writing a TH splice instead of a function. The splice would have to reify ''Num at the call site to determine if a Num instance is in scope, then choose the appropriate function. However, making this work is likely to be more trouble than just writing out the Num instances manually.
Depending on "not a Num a" is very fragile in Haskell in a way that is not fragile in C++.
In C++ the classes are defined in one placed (closed) while Haskell type classes are open and can have instances declared in module C of data from module A and class from module B.
The (no extension) resolution of type classes has a guiding principle that importing a module like "C" would never change the previous resolution of type classes.
Code that expected "not a Num Custom" will change if any recursively imported module (e.g. from another package) defined an "instance Num Custom".
There is an additional problem with polymorphism. Consider a function in module "D"
useSS :: Show a => a -> Int -> [String]
useSS a n = replicate n (showSquare a)
data Custom = Custom deriving Show
use1 :: Int -> String
use1 = useSS Custom -- no Num Custom in scope
Now consider a module "E" in another package which imports the above module "D"
instance Num Custom
use2 :: Int -> String
use2 = useSS Custom -- has a Num Custom now
What should (use1 1) and (use2 1) evaluate to? Do you want to work with a language with traps like this? Haskell is trying to prevent, by principled design, the existence of this trap.
This kind of ad hoc overloading is everywhere in C++ resolution but is exactly what Haskell was designed to avoid. It is possible with GHC extensions to do such things, but one has to be careful not to create dangerous traps, and it is not encouraged.

Resources