When we create a type class, we usually assume that its functions must obey some properties. Thus we have the Monoid and Monad laws for their respective type classes. But, what if there is some law, like associativity, that I want to specify that multiple classes either may or may not obey that law? Is there a way to do that in Haskell's type system? Is this sort of type classes for type classes idea even feasible in practice?
Here's a motivating example from algebra:
class Addition x where
add :: x -> x -> x
class Multiplication x where
mult :: x -> x -> x
instance Addition Int where
add = (+)
instance Multiplication Int where
add = (*)
Now, if I want to specify that addition over Int's is associative and commutative, I can create the classes and instances:
class (Addition x) => AssociativeAddition x where
class (Addition x) => CommutativeAddition x where
instance AssociativeAddition Int where
instance CommutativeAddition Int where
But this is cumbersome because I have to create all possible combinations for all classes. I can't just create Associative and Commutative classes, because what if addition is commutative, but multiplication is not (like in matrices)?
What I would like to be able to do is say something like:
class Associative x where
instance (Associative Addition, Commutative Addition) => Addition Int where
add = (+)
instance (Commutative Multiplication) => Multiplication Int where
mult = (*)
Can this be done?
(Haskell's abstract algebra packages, like algebra and constructive-algebra, do not currently do this, so I'm guessing not. But why not?)
A polymorphic function is called overloaded if its type contains one or more class constraints. (+) :: Num a ⇒ a -> a -> a. For any numeric type a, (+) takes two values of type a and returns a value of type a.
What's a typeclass in Haskell? A typeclass defines a set of methods that is shared across multiple types. For a type to belong to a typeclass, it needs to implement the methods of that typeclass. These implementations are ad-hoc: methods can have different implementations for different types.
A typeclass is a sort of interface that defines some behavior. If a type is a part of a typeclass, that means that it supports and implements the behavior the typeclass describes. A lot of people coming from OOP get confused by typeclasses because they think they are like classes in object oriented languages.
An instance of a class is an individual object which belongs to that class. In Haskell, the class system is (roughly speaking) a way to group similar types. (This is the reason we call them "type classes"). An instance of a class is an individual type which belongs to that class.
You actually can do this with some recent GHC extensions:
{-# LANGUAGE ConstraintKinds, KindSignatures, MultiParamTypeClasses #-}
import GHC.Exts (Constraint)
class Addition (a :: *) where
plus :: a -> a -> a
instance Addition Integer where
plus = (+)
class (c a) => Commutative (a :: *) (c :: * -> Constraint) where
op :: a -> a -> a
instance Commutative Integer Addition where
op = plus
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With