Semantics for GHC extension allowing constraints on methods (-XConstrainedClassMethods) - haskell

The following is quoted from the GHC user guide (Haskell Platform 2012.4.0.0)...
7.6.1.3. Class method types
Haskell 98 prohibits class method types to mention constraints on the class type variable, thus:
class Seq s a where
fromList :: [a] -> s a
elem :: Eq a => a -> s a -> Bool
The type of elem is illegal in Haskell 98, because it contains the constraint Eq a, constrains only the class type variable (in this case a). GHC lifts this restriction (flag -XConstrainedClassMethods).
However, I don't see any explanation of what this means. I can see two possibilities...
The Seq type class implicitly gains the Eq a constraint from elem.
The elem method cannot be used for type class Seq in cases where a is not a member of class Eq (or where it is a member, but that's unknown where elem is used).
I strongly suspect (2) because it seems potentially useful whereas (1) seems useless. (2) basically allows methods to be defined for cases where they can be supported, without limiting the typeclass to only being instanced for those cases.
The example seems to motivate exactly this - the idea being that elem is often a useful operation for sequences, too valuable to live without, yet we also want to support those sequences where elem is unsupportable, such as sequences of functions.
Am I right, or have I missed something? What are the semantics for this extension?

NOTE: it seems like there is a bug in GHC >= 7 that makes GHC accept constrained class methods even in Haskell 98 mode.
Additionally, the example from the manual is always accepted when MultiParamTypeClasses are enabled, regardless of whether the ConstrainedMethodTypes extension is on (also likely a bug).
In the type of elem:
elem :: Eq a => a -> s a -> Bool
a and s are class type variables, and Eq a is a constraint on the class type variable a. As the manual says, Haskell 98 prohibits such constraints (FWIW, it also prohibits multi-parameter type classes). Therefore, the following code shouldn't be accepted in the Haskell 98 mode (and I think it's also prohibited in Haskell 2010):
class Compare a where
comp :: Eq a => a -> a -> Bool
And indeed, GHC 6.12.1 rejects it:
Prelude> :load Test.hs
[1 of 1] Compiling Main ( Test.hs, interpreted )
Test.hs:3:0:
All of the type variables in the constraint `Eq a'
are already in scope (at least one must be universally quantified here)
(Use -XFlexibleContexts to lift this restriction)
When checking the class method: comp :: (Eq a) => a -> a -> Bool
In the class declaration for `Compare'
Failed, modules loaded: none.
Prelude> :set -XConstrainedClassMethods
Prelude> :load Test.hs
[1 of 1] Compiling Main ( Test.hs, interpreted )
Ok, modules loaded: Main.
The idea is that superclass constraints should be used instead:
class (Eq a) => Compare a where
comp :: a -> a -> Bool
Regarding semantics, you can easily check whether a class method constraint implicitly adds a superclass constraint with the following code:
{-# LANGUAGE ConstrainedClassMethods #-}
module Main where
class Compare a where
comp :: (Eq a) => a -> a -> Bool
someMethod :: a -> a -> a
data A = A deriving Show
data B = B deriving (Show,Eq)
instance Compare A where
comp = undefined
someMethod A A = A
instance Compare B where
comp = (==)
someMethod B B = B
Testing with GHC 6.12.1:
*Main> :load Test.hs
[1 of 1] Compiling Main ( Test.hs, interpreted )
Ok, modules loaded: Main.
*Main> comp A
<interactive>:1:0:
No instance for (Eq A)
arising from a use of `comp' at <interactive>:1:0-5
Possible fix: add an instance declaration for (Eq A)
In the expression: comp A
In the definition of `it': it = comp A
*Main> someMethod A A
A
*Main> comp B B
True
Answer: no, it doesn't. The constraint applies only to the method that has a constrained type. So you are right, it's the possibility #2.

Related

Haskell/GHC: overlapping instances reported while context only allows a single one

Dear Haskell/GHC experts,
I don't really understand why GHC reports overlapping instances while only one is actually valid according the provided contexts. For instance, let's consider the following piece of code:
{-# LANGUAGE FlexibleInstances #-}
class C a where
foo :: a -> String
foo x = "OK"
instance C Bool
instance (C a) => C [a]
instance (C a) => C [(Char, a)]
main = print $ foo [('a', True)]
Compiling it gives:
Test.hs:13:16: error:
* Overlapping instances for C [(Char, Bool)]
arising from a use of `foo'
Matching instances:
instance C a => C [a] -- Defined at Test.hs:9:10
instance C a => C [(Char, a)] -- Defined at Test.hs:11:10
* In the second argument of `($)', namely `foo [('a', True)]'
In the expression: print $ foo [('a', True)]
In an equation for `main': main = print $ foo [('a', True)]
The point is that ('a', True) has type (Char, Bool) which is not an instance of C. Therefore, instance C a => C [a] is not applicable to the value [('a', True)].
Therefore, why does GHC consider it?
The question is really about understanding the behaviour of GHC, not about how to avoid the issue (e.g. using OverlappingInstances). Is it because contexts are not used when "resolving" a function call? And if so, why?
Thanks in advance!
My understanding (could be very wrong):
First, from the documentation:
When matching, GHC takes no account of the context of the instance
declaration (context1 etc). GHC's default behaviour is that exactly
one instance must match the constraint it is trying to resolve. It is fine for there to be a potential of overlap (by including both declarations (A) and (B), say); an error is only reported if a particular constraint matches more than one.
The -XOverlappingInstances flag instructs GHC to allow more than one
instance to match, provided there is a most specific one.
In your case, the type passed to foo is [(Char,Bool)]. This satisfies the generic [a] and the more specialised [(Char,a)]. In the absence of OverlappingInstances flag, the most specific match scenario does not apply, and an error is reported.
Now if you were to tweak your code slightly like so:
instance C Bool
instance (C a) => C [a]
instance (C a) => C (Char, a)
Then there would be no overlap, because a tuple is not a list.

Instance Binary of PSQueue

I have want to make a Binary instance for a Priority Sorted Queue from containers. I am using lts-7.0
If Test.hs is
import Data.Binary
import Data.PSQueue
instance Binary a => Binary (PSQ a Int)
running
stack ghci
:set -XFlexibleInstances
:load Test.hs
results in confusing error messages.
~> :load Test.hs
[1 of 1] Compiling Main ( Test.hs, interpreted )
Test.hs:4:10: warning: [-Wdeferred-type-errors]
• Could not deduce (GHC.Generics.Generic (PSQ a Int))
arising from a use of ‘binary-0.8.3.0:Data.Binary.Class.$dmput’
from the context: Binary a
bound by the instance declaration at Test.hs:4:10-39
• In the expression: binary-0.8.3.0:Data.Binary.Class.$dmput
In an equation for ‘put’:
put = binary-0.8.3.0:Data.Binary.Class.$dmput
In the instance declaration for ‘Binary (PSQ a Int)’
Test.hs:4:10: warning: [-Wdeferred-type-errors]
• Could not deduce (GHC.Generics.Generic (PSQ a Int))
arising from a use of ‘binary-0.8.3.0:Data.Binary.Class.$dmget’
from the context: Binary a
bound by the instance declaration at Test.hs:4:10-39
• In the expression: binary-0.8.3.0:Data.Binary.Class.$dmget
In an equation for ‘get’:
get = binary-0.8.3.0:Data.Binary.Class.$dmget
In the instance declaration for ‘Binary (PSQ a Int)’
Ok, modules loaded: Main
How can I get GHC to automatically derive the Binary instance of PSQ a Int?
You unfortunately will need to actually write your own Binary instance for this. On the plus side, that is pretty easy in this case:
import Data.Binary (put, get)
import Data.PSQueue (toAscList, fromAscList, (:->))
instance (Binary a, Binary b, Ord a, Ord b) => Binary (PSQ a b) where
put = put . fmap (\(k :-> v) -> (k,v)) . toAscList
get = fromAscList . fmap (\(k,v) -> k :-> v) <$> get
All this does is convert the priority queue to an ascending list of key-value tuples before/after converting it to/from binary.
Why can't GHC do the work for me?
For GHC to work its magic of deriving the right Binary instance for you, it relies on a special class called Generic that supplies high level information about the data contained in the different constructors. This class is derived (like Read, Show, Eq, etc.) with the DeriveGeneric flag enabled. However, since PSQ does not derive Generic, we might be stuck.
Normally though, there is another trick we can pull: enabling StandaloneDeriving lets us derive as usual, but seperately from the data definition:
deriving instance (Generic (PSQ k v))
But that does require that the constructors of PSQ k v be public (which they are not in this case), so we really can do nothing to derive Generic (PSQ k v). At this point, it is so much simpler to simply write the instance.

Making TypeClass Instance for List

Before getting to my question, let me state my understanding (perhaps incorrect) that a List [] is a higher-kinded type:
ghci> :kind []
[] :: * -> *
I could be mistaken, but, a [] needs a type since it's a List of some type 'T'.
Now to my question.
class Foo a where
bar :: String -> a
Then, I try to create a Foo [String]. My understanding is that the a in Foo a is [String]. So, I'd expect bar to return a [String].
instance Foo [String] where
bar [] = []
bar (x:_) = [x]
However, I get the following compile-time error:
ghci> :l TypeClassExample.hs
[1 of 1] Compiling Main ( TypeClassExample.hs, interpreted )
TypeClassExample.hs:5:10:
Illegal instance declaration for `Foo [String]'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are *distinct type variables*,
and each type variable appears at most once in the instance head.
Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Foo [String]'
Failed, modules loaded: none.
I'm hesitant to add this compile-time flag without understanding it.
What is its significance in this simple code?
The Haskell language definition is quite restrictive, and only allows list instances to be of the form
instance ... => Foo [a] where
where in the head a is exactly a type variable a, disallowing e.g. [Int] or [String].
However, you can require GHC to ignore this restriction. Just add at th beginning of your file the following:
{-# LANGUAGE FlexibleInstances #-}
Many, many modern Haskell programs make use of this. Arguably, in the next Haskell definition revision, this GHC feature should be integrated.

Ambiguous Types, and Defaults for Overloaded Numeric Operations

import Data.Dynamic
default(Integer,Double)
a :: Num a => a
a = 5
-- show :: Show a => a -> String
-- toDyn :: Typeable a => a -> Dynamic
main :: IO ()
-- main = print $ show a -- *** THIS LINE WORKS WELL
main = print $ toDyn a -- *** THIS LINE LEADS TO AN AMBIGUOUS TYPE ERROR
I don't understand why the first "main" version works, and not the second.
Is there someone who can help me ?
Thanks in advance for your reply.
From the Haskell report:
In situations where an ambiguous type is discovered, an ambiguous type variable, v, is defaultable if:
v appears only in constraints of the form C v, where C is a class, and
at least one of these classes is a numeric class, (that is, Num or a subclass of Num), and
all of these classes are defined in the Prelude or a standard library
Your example fails because unlike Show, Typeable is not one of the classes specified in the third point, so no defaulting is performed.

GHCi environment dump

Is there is way in GHCi to basically get a state dump? By this I mean a list of:
All loaded operators along with it's precedence, associativity, and signature.
All loaded classes.
All loaded data, type, and newtype along with what classes they are instances of.
All loaded functions with it's signature, and the class they belong to if they do.
Assuming that this is possible, is it also possible to do this at runtime, say during an exception?
:browse will give you most of this information. It shows
Type signatures for functions and operators.
Classes and their methods.
Data types, newtypes and type synonyms, with constructors if they are in scope.
Without any arguments, it shows this information for the currently loaded module. You can also specify a different module.
Prelude> :browse Control.Applicative
class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
...
To see more detail, including precedence and associativity for operators, as well as instances for a data type, use :info.
Prelude> :info (^)
(^) :: (Num a, Integral b) => a -> b -> a -- Defined in GHC.Real
infixr 8 ^
Prelude> :info Bool
data Bool = False | True -- Defined in GHC.Bool
instance Bounded Bool -- Defined in GHC.Enum
instance Enum Bool -- Defined in GHC.Enum
instance Eq Bool -- Defined in GHC.Base
instance Ord Bool -- Defined in GHC.Base
instance Read Bool -- Defined in GHC.Read
These commands are also available while debugging.
For more information, type :help or see the GHCi chapter of the GHC user's guide.
There are ways of getting this information. The problem is that, as far as I know, there is no way of filtering it exactly the way you want, but anyways here it is:
If you want to see all identifiers, including classes, operators, Constructors, and Types, currently defined in ghci just press tab while you have the cursor on whitespace.
If you want to know the precedence and associativity of an operator * just use
:i *
If you want to see what classes M is instance of just use
:i M
If you want to see the signature of a function f just use
:i f
If you write :set -fbreak-on-exception then ghci will break rather then fail when an exception is thrown and then you can use all of the above commands during an exception.

Resources