Instance Binary of PSQueue - haskell

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.

Related

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.

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

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.

Haskell Ambiguous type error

I have the following definitions
{-# LANGUAGE MultiParamTypeClasses,
FunctionalDependencies,
FlexibleInstances,
FlexibleContexts #-}
import qualified Data.Map as M
class Graph g n e | g -> n e where
empty :: g -- returns an empty graph
type Matrix a = [[a]]
data MxGraph a b = MxGraph { nodeMap :: M.Map a Int, edgeMatrix :: Matrix (Maybe b) } deriving Show
instance (Ord n) => Graph (MxGraph n e) n e where
empty = MxGraph M.empty [[]]
When I try to call empty I get an ambiguous type error
*Main> empty
Ambiguous type variables `g0', `n0', `e0' in the constraint: ...
Why do I get this error? How can I fix it?
You are seeing this type error because Haskell is not provided with sufficient information to know the type of empty.
Any attempt to evaluate an expression though requires the type. The type is not defined yet because the instance cannot be selected yet. That is, as the functional dependency says, the instance can only be selected if type parameter g is known. Simply, it is not known because you do not specify it in any way (such as with a type annotation).
The type-class system makes an open world assumption. This means that there could be many instances for the type class in question and hence the type system is conservative in selecting an instance (even if currently there is only one instance that makes sense to you, but there could be more some other day and the system doesn't want to change its mind just because some other instances get into scope).

Defining an algebra module using constructive-algebra package

The package constructive-algebra allows you to define instances of algebraic modules (like vectorial spaces but using a ring where a field was required)
This is my try at defining a module:
{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-}
module A where
import Algebra.Structures.Module
import Algebra.Structures.CommutativeRing
import Algebra.Structures.Group
newtype A = A [(Integer,String)]
instance Group A where
(A a) <+> (A b) = A $ a ++ b
zero = A []
neg (A a) = A $ [((-k),c) | (k,c) <- a]
instance Module Integer A where
r *> (A as) = A [(r <*> k,c) | (k,c) <- as]
It fails by:
A.hs:15:10:
Overlapping instances for Group A
arising from the superclasses of an instance declaration
Matching instances:
instance Ring a => Group a -- Defined in Algebra.Structures.Group
instance Group A -- Defined at A.hs:9:10-16
In the instance declaration for `Module Integer A'
A.hs:15:10:
No instance for (Ring A)
arising from the superclasses of an instance declaration
Possible fix: add an instance declaration for (Ring A)
In the instance declaration for `Module Integer A'
Failed, modules loaded: none.
If I comment the Group instance out, then:
A.hs:16:10:
No instance for (Ring A)
arising from the superclasses of an instance declaration
Possible fix: add an instance declaration for (Ring A)
In the instance declaration for `Module Integer A'
Failed, modules loaded: none.
I read this as requiring an instance of Ring A to have Module Integer A which doesn't make sense and is not required in the class definition:
class (CommutativeRing r, AbelianGroup m) => Module r m where
-- | Scalar multiplication.
(*>) :: r -> m -> m
Could you explain this?
The package contains an
instance Ring a => Group a where ...
The instance head a matches every type expression, so any instance with any other type expression will overlap. That overlap only causes an error if such an instance is actually used somewhere. In your module, you use the instance in
instance Module Integer A where
r *> (A as) = A [(r <*> k,c) | (k,c) <- as]
The Module class has an AbelianGroup constraint on the m parameter¹. That implies a Group constraint. So for this instance, the Group instance of A must be looked up. The compiler finds two matching instances.
That is the first reported error.
The next is because the compiler tries to find an AbelianGroup instance for A. The only instance the compiler knows about at that point is
instance (Group a, Ring a) => AbelianGroup a
so it tries to find the instance Ring A where ..., but of course there isn't one.
Instead of commenting out the instance Group A where ..., you should add an
instance AbelianGroup a
(even if it's a lie, we just want to make it compile at the moment) and also add OverlappingInstances to the
{-# LANGUAGE #-} pragma.
With OverlappingInstances, the most specific matching instance is chosen, so it does what you want here.
¹ By the way, your A isn't an instance of AbelianGroup and rightfully can't be unless order is irrelevant in the [(Integer,String)] list.
This type checks without obnoxious language extensions.
{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-}
module A where
import Algebra.Structures.Module
import Algebra.Structures.CommutativeRing
import Algebra.Structures.Group
newtype A = A [(Integer,String)]
instance Ring A where
A xs <+> A ys = A (xs ++ ys)
neg (A a) = A $ [((-k),c) | (k,c) <- a]
A x <*> A y = A [b | a <- x, b <- y ]
one = A []
zero = A []
instance Module Integer A where
r *> (A as) = A [(r <*> k,c) | (k,c) <- as]
It is a little confusing that <+> <*> and neg are defined independently in Ring and Group; they are completely separate symbols, but then they are brought together in the general instance that makes all Rings Groups, so if Ring is defined, Group mustn't be defined, since it's already spoken for. I'm not sure this is forced on the author by the way the type class system works. Module requires Ring or rather CommutativeRing. CommutativeRing is just basically renaming Ring; nothing further is to be defined. It is supposed to commit you to what is in Haskell an uncheckable assertion of commutativity. So you are supposed to "prove the CommutativeRing laws", so to speak, outside the module before making the Module instance. Note however that these laws are expressed in quickcheck propositions, so you are supposed to run quickcheck on propMulComm and propCommutativeRing specialized to this type.
Don't know what to do about one and zero, but you can get past the point about order by using a suitable structure, maybe:
import qualified Data.Set as S
newtype B = B {getBs :: S.Set (Integer,String) }
But having newtyped you can also, e.g., redefine Eq on A's to make sense of it, I suppose. In fact you have to to run the quickcheck propositions.
Edit: Here is a version with added material needed for QuickCheck http://hpaste.org/68351 together with "Failed" and "OK" quickcheck-statements for different Eq instances. This package is seeming pretty reasonable to me; I think you should redefine Module if you don't want the Ring and CommutativeRing business, since he says he "Consider[s] only the commutative case, it would be possible to implement left and right modules instead." Otherwise you won't be able to use quickcheck, which is clearly the principal point of the package, now that I see what's up, and which he has made it incredibly easy to do. As it is A is exactly the kind of thing he is trying to rule out with the all-pervasive use of quickcheck, which it would surely be very hard to trick in this sort of case.

How do I resolve this compile error: Ambiguous type variable `a1' in the constraint

One could think of this case as follows:
The application dynamically loads a module, or there is a list of functions from which the user chooses, etc. We have a mechanism for determining whether a certain type will successfully work with a function in that module. So now we want to call into that function. We need to force it to make the call. The function could take a concrete type, or a polymorphic one and it's the case below with just a type class constraint that I'm running into problems with it.
The following code results in the errors below. I think it could be resolved by specifying concrete types but I do not want to do that. The code is intended to work with any type that is an instance of the class. Specifying a concrete type defeats the purpose.
This is simulating one part of a program that does not know about the other and does not know the types of what it's dealing with. I have a separate mechanism that allows me to be sure that the types do match up properly, that the value sent in really is an instance of the type class. That's why in this case, I don't mind using unsafeCoerce. But basically I need a way to tell the compiler that I really do know it's ok and do it anyway even though it doesn't know enough to type check.
{-# LANGUAGE ExistentialQuantification, RankNTypes, TypeSynonymInstances #-}
module Main where
import Unsafe.Coerce
main = do
--doTest1 $ Hider "blue"
doTest2 $ Hider "blue"
doTest1 :: Hider -> IO ()
doTest1 hh#(Hider h) =
test $ unsafeCoerce h
doTest2 :: Hider -> IO ()
doTest2 hh#(Hider h) =
test2 hh
test :: HasString a => a -> IO ()
test x = print $ toString x
test2 :: Hider -> IO ()
test2 (Hider x) = print $ toString (unsafeCoerce x)
data Hider = forall a. Hider a
class HasString a where
toString :: a -> String
instance HasString String where
toString = id
Running doTest1
[1 of 1] Compiling Main ( Test.hs, Test.o )
Test.hs:12:3:
Ambiguous type variable `a1' in the constraint:
(HasString a1) arising from a use of `test'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: test
In the expression: test $ unsafeCoerce h
In an equation for `doTest1':
doTest1 hh#(Hider h) = test $ unsafeCoerce h
Running doTest2
[1 of 1] Compiling Main ( Test.hs, Test.o )
Test.hs:12:3:
Ambiguous type variable `a1' in the constraint:
(HasString a1) arising from a use of `test'
Probable fix: add a type signature that fixes these type variable(s)
In the expression: test
In the expression: test $ unsafeCoerce h
In an equation for `doTest1':
doTest1 hh#(Hider h) = test $ unsafeCoerce h
I think it could be resolved by specifying concrete types but I do not want to do that.
There's no way around it though with unsafeCoerce. In this particular case, the compiler can't infer the type of unsafeCoerce, because test is still to polymorphic. Even though there is just one instance of HasString, the type system won't use that fact to infer the type.
I don't have enough information about your particular application of this pattern, but I'm relatively sure that you need to rethink the way you use the type system in your program. But if you really want to do this, you might want to look into Data.Typeable instead of unsafeCoerce.
Modify your data type slightly:
data Hider = forall a. HasString a => Hider a
Make it an instance of the type class in the obvious way:
instance HasString Hider where
toString (Hider x) = toString x
Then this should work, without use of unsafeCoerce:
doTest3 :: Hider -> IO ()
doTest3 hh = print $ toString hh
This does mean that you can no longer place a value into a Hider if it doesn't implement HasString, but that's probably a good thing.
There's probably a name for this pattern, but I can't think what it is off the top of my head.

Resources