Converting an arbitrary class constraint `C a` into `C a Bool` - haskell

So there are many advantages of having typeclasses in C a Bool form. Mostly because they let you do any logical operation between two constraints when the normal C a just implicitly ANDs everything.
If we consider ~ a class constraint, this can be done like so
class Equal x y b | x y -> b
instance Equal x x True
instance False ~ b => Equal x y b
But what makes this case special is the fact that putting x x in the head of the instance is equivalent to x ~ y => and then x y in the head. This is not the case for any other typeclass.
So if we try to do something similar for a class C we get something like
class C' x b | x -> b
instance C x => C' x True
instance False ~ Bool => C' x b
Unfortunately this doesn't work since only one of those instances will ever be picked because they don't discriminate on the type x so any type matches both heads.
I've also read https://www.haskell.org/haskellwiki/GHC/AdvancedOverlap which again doesn't apply for any class C because it requires you to rewrite all the instances of the original class. Ideally, I'd like my code to work with GHC.Exts.Constraint and KindSignatures so that C can be parametric.
So, for a class like this
class Match (c :: * -> Constraint) x b | c x -> b
How do I write the instances so that Match c x True if and only if c x, Match c x False otherwise?

This is impossible in Haskell due to the so-called Open World Assumption. It states that the set of instances for typeclasses is open, which means that you can make new instances any time (as opposed to a closed world, where there must be a fixed set of instances). For example, while the Functor typeclass is defined in the Prelude, I can still make instances for it in my own code which is not in the Prelude.
To implement what you've proposed, the compiler would need a way to check whether a type T is an instance of a class C. This, however, requires that the compiler knows all the possible instances of that class and that is not possible because of the open world assumption (while compiling the Prelude, a compiler can't yet know that you later make YourOwnFunctor an instance of Functor too).
The only way to make it work would be to only consider the instances that are currently visible (because they were defined in the current module or any of its imports). But that would lead to quite unpredictable behaviour: the set of visible instances depends not only on the imports of the module, but also on the imports of the imports since you cannot hide instances. So the behaviour of your code would depend on implementation details of your dependencies.
If you want a closed world, you can instead use closed type families, which were introduced in GHC 7.8. Using them, you can write:
type family Equal a b :: Bool where
Equal x x = True
Equal x y = False

Related

Overlapping instances and ORing constraints

I want to have a class which represents a property P x and I have an implication of the form A x \or B x => P x.
I have tried to implement this as follows:
class P x
instance A x => P x
instance B x => P x
However this fails with overlapping instances if both A x and B x hold.
(I encountered this when dealing with natural numbers, Max and Min functions)
What is the correct way of expressing this constraint?
#Li-yaoXia is correct to say you can't do this. #Chi's explanation isn't what's going on. The => in an instance decl is not implication (at least not in the Prolog sense).
instance A x => P x
Means x is an instance of class P. Typically the x will be a concrete type like Int, or at least a type constructor with argument variables like Maybe a. The => then says: for type x an instance of P, require A x. That is, the implication goes the opposite way to how it looks.
It's a (common) newbie mistake to think it means 'first check all constraints hold then check if the instance head holds.'
Then also having
instance B x => P x
means x is an instance of P; also require B x. So if your two instances were to compile, you'd be requiring (P x) IMPLIES ((A x) AND (B x)). That is, the same as
instance (A x, B x) => P x
But your instances don't compile. Because their two heads are identical P x; that's a repeat. (I expect not an overlapping instances error, but a repeated instance error.)
Overlapping instances are nothing to do with what's going on here. (But #Chi is wrong to suggest they require any sort of indeterminism: if you try to write indeterministic overlapping instances, usually the program gets rejected. Unless you switch on all sorts of dangerous extensions.)

Haskell: function to find out by type definition

Also owing to all your help, I made some steps in understanding the type system in Haskell. What I still don't understand is a construction like this:
chk :: Eq b => (a -> b) -> a -> b -> Bool
Why is the class constraint only on 'b', while you cannot compare different types?
Isn't a/b used to indicate different types anyway?
If I got this all wrong, can you show me a function that would typecheck like that?
Such a function would only be able to compare two values of type b for equality, no as involved.
If you look at the type, there is one implementation that seems to be the obvious one:
chk :: Eq b => (a -> b) -> a -> b -> Bool
chk f x y =
let z = f x -- z :: b
in y == z -- comparison of two values of type b
You need to clearly separate in your mind the difference between type variables and normal variables.
The type (Eq b) =>... means that b can be any type, provided that values of that type are comparable. So b = Int would work, because we can compare Int values (e.g., 3 == 5 is false, but 2 == 2 is true). But b = IO Int would not work, since you cannot compare I/O operations for equality.
All of this has nothing to do with whether a == b; both a and b are types, not values. The type says that a can be any type, and b can also be any type (if it implements Eq). In particular, it's possible for a and b to be the same type, but it's also possible for them to be different types. Using different type variables says that these can be different types, not that they must be different.
Ler's see how we could deduce a sensible implementation of chk from its type.
Having two values, one of type a and one of type b, we can't do much with them. Both types are unknown. (They may be in fact the same type but we don't know that). We know we can compare two values of type b for equality, but there's only one such value at our disposal. We can compare it with itself but this doesn't make much sense. If we had another value of type b, we could compare the two.
But there are three arguments, one of type a, one of type b, and one is a function of type a->b. The only other thing we can do with them (apart from comparing a value with itself) is to apply the function to the value of type a. The result of this application has type b. But wait, this is exactly what we wanted, another value of type b to complete the comparison. And since the result of the comparison is of type Bool, this is exactly what we need to complete chk.
chk f x y = f x == y
And this is the one of two non-trivial ways to write this function. The other one replaces == with /=.
There are in fact a very limited amount of functions of this type and we can enumerate them all. If you only take into account total functions and require that equality is reflexive and symmetric, then there are only two other functions of this type:
chk0 f x y = True
chk1 f x y = False
If you drop these restrictions, you can write also:
chk2 f x y = undefined
chk3 f x y = y == y // may be different from just True
chk4 f x y = f x == f x
and perhaps a dozen more.

Why context is not considered when selecting typeclass instance in Haskell?

I understand that when having
instance (Foo a) => Bar a
instance (Xyy a) => Bar a
GHC doesn't consider the contexts, and the instances are reported as duplicate.
What is counterintuitive, that (I guess) after selecting an instance, it still needs to check if the context matches, and if not, discard the instance. So why not reverse the order, and discard instances with non-matching contexts, and proceed with the remaining set.
Would this be intractable in some way? I see how it could cause more constraint resolution work upfront, but just as there is UndecidableInstances / IncoherentInstances, couldn't there be a ConsiderInstanceContexts when "I know what I am doing"?
This breaks the open-world assumption. Assume:
class B1 a
class B2 a
class T a
If we allow constraints to disambiguate instances, we may write
instance B1 a => T a
instance B2 a => T a
And may write
instance B1 Int
Now, if I have
f :: T a => a
Then f :: Int works. But, the open world assumption says that, once something works, adding more instances cannot break it. Our new system doesn't obey:
instance B2 Int
will make f :: Int ambiguous. Which implementation of T should be used?
Another way to state this is that you've broken coherence. For typeclasses to be coherent means that there is only one way to satisfy a given constraint. In normal Haskell, a constraint c has only one implementation. Even with overlapping instances, coherence generally holds true. The idea is that instance T a and instance {-# OVERLAPPING #-} T Int do not break coherence, because GHC can't be tricked into using the former instance in a place where the latter would do. (You can trick it with orphans, but you shouldn't.) Coherence, at least to me, seems somewhat desirable. Typeclass usage is "hidden", in some sense, and it makes sense to enforce that it be unambiguous. You can also break coherence with IncoherentInstances and/or unsafeCoerce, but, y'know.
In a category theoretic way, the category Constraint is thin: there is at most one instance/arrow from one Constraint to another. We first construct two arrows a : () => B1 Int and b : () => B2 Int, and then we break thinness by adding new arrows x_Int : B1 Int => T Int, y_Int : B2 Int => T Int such that x_Int . a and y_Int . b are both arrows () => T Int that are not identical. Diamond problem, anyone?
This does not answer you question as to why this is the case. Note, however, that you can always define a newtype wrapper to disambiguate between the two instances:
newtype FooWrapper a = FooWrapper a
newtype XyyWrapper a = XyyWrapper a
instance (Foo a) => Bar (FooWrapper a)
instance (Xyy a) => Bar (XyyWrapper a)
This has the added advantage that by passing around either a FooWrapper or a XyyWrapper you explicitly control which of the two instances you'd like to use if your a happens to satisfy both.
Classes are a bit weird. The original idea (which still pretty much works) is a sort of syntactic sugar around what would otherwise be data statements. For example you can imagine:
data Num a = Num {plus :: a -> a -> a, ... , fromInt :: Integer -> a}
numInteger :: Num Integer
numInteger = Num (+) ... id
then you can write functions which have e.g. type:
test :: Num x -> x -> x -> x -> x
test lib a b c = a + b * (abs (c + b))
where (+) = plus lib
(*) = times lib
abs = absoluteValue lib
So the idea is "we're going to automatically derive all of this library code." The question is, how do we find the library that we want? It's easy if we have a library of type Num Int, but how do we extend it to "constrained instances" based on functions of type:
fooLib :: Foo x -> Bar x
xyyLib :: Xyy x -> Bar x
The present solution in Haskell is to do a type-pattern-match on the output-types of those functions and propagate the inputs to the resulting declaration. But when there's two outputs of the same type, we would need a combinator which merges these into:
eitherLib :: Either (Foo x) (Xyy x) -> Bar x
and basically the problem is that there is no good constraint-combinator of this kind right now. That's your objection.
Well, that's true, but there are ways to achieve something morally similar in practice. Suppose we define some functions with types:
data F
data X
foobar'lib :: Foo x -> Bar' x F
xyybar'lib :: Xyy x -> Bar' x X
bar'barlib :: Bar' x y -> Bar x
Clearly the y is a sort of "phantom type" threaded through all of this, but it remains powerful because given that we want a Bar x we will propagate the need for a Bar' x y and given the need for the Bar' x y we will generate either a Bar' x X or a Bar' x y. So with phantom types and multi-parameter type classes, we get the result we want.
More info: https://www.haskell.org/haskellwiki/GHC/AdvancedOverlap
Adding backtracking would make instance resolution require exponential time, in the worst case.
Essentially, instances become logical statements of the form
P(x) => R(f(x)) /\ Q(x) => R(f(x))
which is equivalent to
(P(x) \/ Q(x)) => R(f(x))
Computationally, the cost of this check is (in the worst case)
c_R(n) = c_P(n-1) + c_Q(n-1)
assuming P and Q have similar costs
c_R(n) = 2 * c_PQ(n-1)
which leads to exponential growth.
To avoid this issue, it is important to have fast ways to choose a branch, i.e. to have clauses of the form
((fastP(x) /\ P(x)) \/ (fastQ(x) /\ Q(x))) => R(f(x))
where fastP and fastQ are computable in constant time, and are incompatible so that at most one branch needs to be visited.
Haskell decided that this "fast check" is head compatibility (hence disregarding contexts). It could use other fast checks, of course -- it's a design decision.

Haskell TypeCast type class

I've run into a type class called TypeCast in Haskell in a few different places.
It's rather cryptic, and I can't seem to fully parse it.
class TypeCast a b | a -> b, b -> a where typeCast :: a -> b
class TypeCast' t a b | t a -> b, t b -> a where typeCast' :: t -> a -> b
class TypeCast'' t a b | t a -> b, t b -> a where typeCast'' :: t -> a -> b
instance TypeCast' () a b => TypeCast a b where typeCast x = typeCast' () x
instance TypeCast'' t a b => TypeCast' t a b where typeCast' = typeCast''
instance TypeCast'' () a a where typeCast'' _ x = x
http://okmij.org/ftp/Haskell/typecast.html gives a helpful but perfunctory comment on this code. For more information, that page points me to http://homepages.cwi.nl/~ralf/HList/paper.pdf which is a broken link.
I see that TypeCast is a class that allows you to cast from one type to another, but I don't see why we need TypeCast' and TypeCast''.
It looks like all this code does is allow you to cast a type to itself. In some of the sample code I've seen, I tried replacing it with this:
class TypeCast a b | a -> b, b -> a where typeCast :: a -> b
instance TypeCast a a where typeCast a = a
and the samples still worked. The samples I've been looking at are mostly from that first link.
I was wondering if someone could explain what the six lines are for.
What is TypeCast actually for?
It isn't used for retrieving type information about existential types (that would break the type system, so it is impossible). To understand TypeCast, we first have to understand some particular details about the haskell type system. Consider the following motivating example:
data TTrue
data TFalse
class TypeEq a b c | a b -> c
instance TypeEq x x TTrue
instance TypeEq x y TFalse
The goal here is to have a boolean flag - on the type level - which tells you if two types are equal. You can use ~ for type equivalence - but this only gives you failure on type in equivalence (ie Int ~ Bool doesn't compile as opposed to TypeEq Int Bool r will give r ~ TFalse as the inferred type). However, this doesn't compile - the functional dependencies conflict. The reason is simple - x x is just an instantiation of x y (ie x ~ y => x y == x x), so according to the rules of fundeps (see the docs for full details of the rules) , the two instances must have the same value for c (or the two values must be insantiations of one another - which they aren't).
The TypeEq class exists in the HList library - lets take a look how it is implemented:
class HBool b => TypeEq x y b | x y -> b
instance TypeEq x x HTrue
instance (HBool b, TypeCast HFalse b) => TypeEq x y b
-- instance TypeEq x y HFalse -- would violate functional dependency
Naturally these instance don't conflict - HTrue is an instantiation of b. But wait! Doesn't TypeCast HFalse b imply that b must be HFalse? Yes, it does, but the compiler does not check the class instance constraint when attempting to resolve fundep conflicts. This is the key 'feature' which allows this class to exist.
As a brief note - the two instances still overlap. But with -XUndecidableInstances -XOverlappingInstances, the compiler will choose the first instance preferentially, due to the fact that the first instance is more 'specific' (in this case, that means it has at most 2 unique types - x and HTrue, while the other instance has at most 3). You can find the full set of rules that UndecidableInstances uses in the docs.
Why is TypeCast written the way it is?
If you look in the source for HList, there are multiple implementations of TypeCast. One implementation is:
instance TypeCast x x
The straightforward instance one would assume will work. Nope! From the comments in the file containing the above definition:
A generic implementation of type cast. For this implementation to
work, we need to import it at a higher level in the module hierarchy
than all clients of the class. Otherwise, type simplification will
inline TypeCast x y, which implies compile-time unification of x and y.
That is, the type simplifier (whose job it is to remove uses of type synonyms and constant class constraints) will see that x ~ y in TypeCast x x since that is the only instance that matches, but only in certain situations. Since code that behaves differently in different cases is 'Very Bad', the authors of HList have a second implementation, the one in your original post. Lets take a look:
class TypeCast a b | a -> b, b -> a
class TypeCast' t a b | t a -> b, t b -> a
class TypeCast'' t a b | t a -> b, t b -> a
instance TypeCast' () a b => TypeCast a b
instance TypeCast'' t a b => TypeCast' t a b
instance TypeCast'' () a a
In this case, TypeCast x y can never be simplified without looking at the class constraint (which the simplifier will not do!); there is no instance head which can imply x ~ y.
However, we still need to assert that x ~ y at some point in time - so we do it with more classes!
The only way we can know a ~ b in TypeCast a b is if TypeCast () a b implies a ~ b. This is only the case if TypeCast'' () a b implies a ~ b, which it does.
I can't give you the whole story unfortunatley; I don't know why
instance TypeCast' () a b => TypeCast a b
instance TypeCast' () a a
doesn't suffice (it works - I don't know why it wouldn't be used). I suspect it has something to do with error messages. I'm sure you could track down Oleg and ask him!
The HList paper was published in the proceedings of the Haskell Workshop 2004, and so is available from the ACM DL and other archives. Alas, the explanation in the published version is abbreviated for the lack of space. For full explanation, please see the expanded version of the paper published as a Technical Report, which is available at
http://okmij.org/ftp/Haskell/HList-ext.pdf (The CWI link is indeed no longer valid since Ralf left CWI long time ago.) Please see Appendix D in that TR for the explanation of TypeCast.
In the latest GHC, instead of TypeCast x y constraint you can write x ~ y. There is no corresponding typeCast method: it is no longer necessary. When you write the x ~ y constraint, GHC synthesizes something like typeCast (called coercion) automatically and behind the scenes.
Asking me a question directly in a e-mail message usually results in a much faster reply.

How can I combine two type constraints with a logical or in Haskell?

In Haskell we are given the ability to combine constraints on types with a logical and.
Consider the following
type And (a :: Constraint) b = (a, b)
or more complicatedly
class (a, b) => And a b
instance (a, b) => And a b
I want to know how to logically or two constraints together in Haskell.
My closest attempt is this, but it doesn't quite work. In this attempt I reify type constraints with tags and than dereify them with implicit parameters.
data ROr a b where
L :: a => ROr a b
R :: b => ROr a b
type Or a b = (?choose :: ROr a b)
y :: Or (a ~ Integer) (Bool ~ Integer) => a
y = case ?choose of
L -> 4
x :: Integer
x = let ?choose = L in y
It almost works, but the user has to apply the final part, and the compiler should do that for me. As well, this case does not let one choose a third choice when both constraints are satisfied.
How can I logically or two constraints together?
I believe that there is no way to automatically pick an ROr a b; it would violate the open world assumption if, e.g. b was satisfied, but later a was satisfied as well; any conflict resolution rule would necessarily cause the addition of an instance to change the behaviour of existing code.
That is, picking R when b is satisfied but a is not breaks the open world assumption, because it involves deciding that an instance is not satisfied;1 even if you added a "both satisfied" constructor, you would be able to use it to decide whether an instance is not present (by seeing if you get an L or an R).
Therefore, I do not believe that such an or constraint is possible; if you can observe which instance you get, then you can create a program whose behaviour changes by adding an instance, and if you can't observe which instance you get, then it's pretty useless.
1 The difference between this and normal instance resolution, which can also fail, is that normally, the compiler cannot decide that a constraint is satisfied; here, you're asking the compiler to decide that the constraint cannot be satisfied. A subtle but important difference.
I came here to answer your question on the cafe. Not sure the q here is the same, but anyway ...
a type class with three parameters.
class Foo a b c | a b -> c where
foo :: a -> b -> c
instance Foo A R A where ...
instance Foo R A A where ...
In addition to the functional dependency I'd like to express that at least one of the parameters a and b is c,
import Data.Type.Equality
import Data.Type.Bool
class ( ((a == c) || (b == c)) ~ True)
=> Foo a b c | a b -> c where ...
You'll need a bunch of extensions switched on. In particular UndecidableSuperClasses, because the type family calls in the class constraint are opaque as far as GHC can see.
Your q here
How can I logically or two constraints together?
Is far more tricky. For the type equality approach, == uses a Closed Type Family. So you could write a Closed Type Family returning kind Constraint, but I doubt there's a general solution. For your Foo class:
type family AorBeqC a b c :: Constraint where
AorBeqC a b a = ()
AorBeqC a b c = (b ~ c)
class AorBeqC a b c => Foo a b c | a b -> c where ...
It's likely to have poor and non-symmetrical type improvement behaviour: if GHC can see that a, c are apart, it'll go to the second equation and use (b ~ c) to improve either; if it can't see they're apart nor that they're unifiable, it'll get stuck.
In general, as #ehird points out, you can't test whether a constraint is not satisfiable. Type equality is special.

Resources