Show Constraint type in haskell - haskell

I am trying to use show function to print to the console value of zer or one, but I can not do it. Here is my code:
{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Arrow
import Data.List
import qualified Data.Map as M
import Data.Function
class 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'
I am trying to use function show to convert zer or one to the string.
So I tried it:
k = zer
show k
but I got this error
<interactive>:10:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘show’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance (Show k, Show a) => Show (M.Map k a)
-- Defined in ‘containers-0.5.7.1:Data.Map.Base’
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
...plus 24 others
...plus 11 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: show zer
In an equation for ‘it’: it = show zer
so i tried to create instance for show. So I added this to my code:
instance (Show a) => Show (Bits a) where
show zer = "0"
show one = "1"
But I got another error
main.hs:25:28: error:
• Expected a type, but ‘Bits a’ has kind ‘Constraint’
• In the first argument of ‘Show’, namely ‘Bits a’
In the instance declaration for ‘Show (Bits a)’
Can you tell me what I am doing wrong?

You're trying to make a class an instance of a class, rather than making a type an instance of a class. Compare:
Show a => Show (Bits a) -- Invalid
to
Show a => Show (Maybe a) -- Valid
where Maybe is a datatype whereas Bits is a class name.
I don't think it's possible to express "anything that has a Bits instance has a Show instance", because it can lead to overlapping instances: if you could define something like that, then when you use show :: Int -> String the compiler wouldn't know whether to use the Prelude's instance of Show Int or the show that would be defined by Int being an instance of Bits.
A messy workaround could be to enforce "the other direction": that every instance of Bits must be an instance of Show, which would allow you to use a's Show instance rather than your own one:
class (Show a, Eq a) => Bits a where
zer :: a
one :: a
main = print (zer :: Int)
although this requires an explicit type signature to resolve the ambiguity in the type of zer at the call site.

Related

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

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

Why can't Haskell function return a list

What is wrong with that:
partin a = [floor a, a-floor a]
Error :
<interactive>:342:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 16 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of an interactive GHCi command: print it
I can't give a complete answer without seeing the full extent of what you're doing, but here's one definite problem that is almost certainly involved. You write
partin a = [floor a, a-floor a]
The type of floor is
floor :: (RealFrac a, Integral b) => a -> b
The type of (-) is
(-) :: Num a => a -> a -> a
Since you use a - floor a, you're forcing the type of a to be an instance of both the RealFrac class and the Integral class. However, there is no such type in the standard library (and it doesn't make a lot of sense). As a result, GHC certainly will not be able to select the type for you from its very limited collection of defaults. Things might work out a lot better if you use
partin a = [fromIntegral (floor a), a - fromIntegral (floor a :: Int)]
But note that it doesn't really make much sense to have a list here, since you're trying to divide a number into two components of different types. You might be better off with
partin a = (floor a, a - fromIntegral (floor a :: Int))

Default to a typeclass when a data type does not instantiate it [duplicate]

What I'd like to achieve is that any instance of the following class (SampleSpace) should automatically be an instance of Show, because SampleSpace contains the whole interface necessary to create a String representation and hence all possible instances of the class would be virtually identical.
{-# LANGUAGE FlexibleInstances #-}
import Data.Ratio (Rational)
class SampleSpace space where
events :: Ord a => space a -> [a]
member :: Ord a => a -> space a -> Bool
probability :: Ord a => a -> space a -> Rational
instance (Ord a, Show a, SampleSpace s) => Show (s a) where
show s = showLines $ events s
where
showLines [] = ""
showLines (e:es) = show e ++ ": " ++ (show $ probability e s)
++ "\n" ++ showLines es
Since, as I found out already, while matching instance declarations GHC only looks at the head, and not at contraints, and so it believes Show (s a) is about Rational as well:
[1 of 1] Compiling Helpers.Probability ( Helpers/Probability.hs, interpreted )
Helpers/Probability.hs:21:49:
Overlapping instances for Show Rational
arising from a use of ‘show’
Matching instances:
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance (Ord a, Show a, SampleSpace s) => Show (s a)
-- Defined at Helpers/Probability.hs:17:10
In the expression: show
In the first argument of ‘(++)’, namely ‘(show $ probability e s)’
In the second argument of ‘(++)’, namely
‘(show $ probability e s) ++ "" ++ showLines es
Question: is it possible (otherwise than by enabling overlapping instances) to make any instance of a typeclass automatically an instance of another too?
tl;dr: don't do that, or, if you insist, use -XOverlappingInstances.
This is not what the Show class is there for. Show is for simply showing plain data, in a way that is actually Haskell code and can be used as such again, yielding the original value.
SampleSpace should perhaps not be a class in the first place. It seems to be basically the class of types that have something like Map a Rational associated with them. Why not just use that as a field in a plain data type?
Even if we accept the design... such a generic Show instance (or, indeed, generic instance for any single-parameter class) runs into problems when someone makes another instance for a concrete type – in the case of Show, there are of course already plenty of instances around. Then how should the compiler decide which of the two instances to use? GHC can do it, in fact: if you turn on the -XOverlappingInstances extension, it will select the more specific one (i.e. instance SampleSpace s => Show (s a) is “overridden” by any more specific instance), but really this isn't as trivial as may seem – what if somebody defined another such generic instance? Crucial to recall: Haskell type classes are always open, i.e. basically the compiler has to assume that all types could possibly in any class. Only when a specific instance is invoke will it actually need the proof for that, but it can never proove that a type isn't in some class.
What I'd recommend instead – since that Show instance doesn't merely show data, it should be made a different function. Either
showDistribution :: (SampleSpace s, Show a, Ord a) => s a -> String
or indeed
showDistribution :: (Show a, Ord a) => SampleSpace a -> String
where SampleSpace is a single concrete type, instead of a class.

Show list of unknown type in Haskell

I was given an assignment in which I should have the type signature
Group g => Int -> Int -> [[g]]
However if g is ambiguous how can I print it? I get this error:
No instance for (Show g0) arising from a use of ‘print’
The type variable ‘g0’ is ambiguous
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 24 others
In the expression: print
In the expression: print $ myTest 10 0
In an equation for ‘main’: main = print $ myTest 10 0
Which makes sense to me. Is there an error in the assignment? Or is there a way to print an ambiguous type?
Try running
> :info Group
This should print out the Group typeclass and its members, followed by a list of instances. Pick one of these instances, then execute
> myTest 1 2 :: [[TheTypeYouPicked]]
If you wanted to use it inside main you'll have to give it a type signature there too:
main :: IO ()
main = print (myTest 10 0 :: [[TheTypeYouPicked]])
The reason why the compiler is showing you this error is because there could be many instances of Group to choose from, not all of them necessarily implement Show as well. In order to print something in the console, either by just executing it (there's an implicit print when you just run a normal function in GHCi) or with an explicit print it needs to implement Show.

Make a typeclass instance automatically an instance of another

What I'd like to achieve is that any instance of the following class (SampleSpace) should automatically be an instance of Show, because SampleSpace contains the whole interface necessary to create a String representation and hence all possible instances of the class would be virtually identical.
{-# LANGUAGE FlexibleInstances #-}
import Data.Ratio (Rational)
class SampleSpace space where
events :: Ord a => space a -> [a]
member :: Ord a => a -> space a -> Bool
probability :: Ord a => a -> space a -> Rational
instance (Ord a, Show a, SampleSpace s) => Show (s a) where
show s = showLines $ events s
where
showLines [] = ""
showLines (e:es) = show e ++ ": " ++ (show $ probability e s)
++ "\n" ++ showLines es
Since, as I found out already, while matching instance declarations GHC only looks at the head, and not at contraints, and so it believes Show (s a) is about Rational as well:
[1 of 1] Compiling Helpers.Probability ( Helpers/Probability.hs, interpreted )
Helpers/Probability.hs:21:49:
Overlapping instances for Show Rational
arising from a use of ‘show’
Matching instances:
instance (Integral a, Show a) => Show (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance (Ord a, Show a, SampleSpace s) => Show (s a)
-- Defined at Helpers/Probability.hs:17:10
In the expression: show
In the first argument of ‘(++)’, namely ‘(show $ probability e s)’
In the second argument of ‘(++)’, namely
‘(show $ probability e s) ++ "" ++ showLines es
Question: is it possible (otherwise than by enabling overlapping instances) to make any instance of a typeclass automatically an instance of another too?
tl;dr: don't do that, or, if you insist, use -XOverlappingInstances.
This is not what the Show class is there for. Show is for simply showing plain data, in a way that is actually Haskell code and can be used as such again, yielding the original value.
SampleSpace should perhaps not be a class in the first place. It seems to be basically the class of types that have something like Map a Rational associated with them. Why not just use that as a field in a plain data type?
Even if we accept the design... such a generic Show instance (or, indeed, generic instance for any single-parameter class) runs into problems when someone makes another instance for a concrete type – in the case of Show, there are of course already plenty of instances around. Then how should the compiler decide which of the two instances to use? GHC can do it, in fact: if you turn on the -XOverlappingInstances extension, it will select the more specific one (i.e. instance SampleSpace s => Show (s a) is “overridden” by any more specific instance), but really this isn't as trivial as may seem – what if somebody defined another such generic instance? Crucial to recall: Haskell type classes are always open, i.e. basically the compiler has to assume that all types could possibly in any class. Only when a specific instance is invoke will it actually need the proof for that, but it can never proove that a type isn't in some class.
What I'd recommend instead – since that Show instance doesn't merely show data, it should be made a different function. Either
showDistribution :: (SampleSpace s, Show a, Ord a) => s a -> String
or indeed
showDistribution :: (Show a, Ord a) => SampleSpace a -> String
where SampleSpace is a single concrete type, instead of a class.

Resources