Reputation:
I'm trying to create a "hierarchy" of algebraic type classes, as follows:
class Semigroup a where
(.*) :: a -> a -> a
foldr1 (.*) = foldl1 (.*) -- GHCi error: "`foldr1' is not a (visible) method of class `Semigroup'"
class (Semigroup a) => Monoid a where
identity :: a
(.*) identity = id :: a -> a -- GHCi error: "`.*' is not a (visible) method of class `Monoid'"
class (Monoid a) => Group a where
inverse :: a -> a
Thus, groups are monoids and monoids are semigroups. However, I get errors that the classes can't see the functions of their parent class.
These errors bug me because I assumed that by writing (for example) class (Semigroup a) => Monoid a
the class Monoid a
would be able to see the function (.*)
. And furthermore, the type of foldr1
in the Prelude has no constraints, so I assumed that foldr1
would work in this context.
Upvotes: 5
Views: 1676
Reputation: 152837
Haskell does not allow you to declare (or enforce) equations on terms (like it seems like you want to do). This is for a very practical reason: proving equalities between arbitrary terms in a programming language as rich as Haskell is undecidable. Checking a human-constructed proof is often decidable, but it is also somewhat annoying to have to write and track these proofs while programming.
Still, if this is the kind of thing you want to do on a regular basis, there are languages that make this possible; the term to search for is "dependent types". For example, Coq and Agda are perhaps the two most popular dependently typed languages at the moment, and each would make it dead-simple to write a type inhabited only by good, law-abiding semigroups (or monoids).
Upvotes: 6
Reputation: 47052
I'm not sure what you're trying to do.
If you're trying to provide a default value for foldr1
in Semigroup
, and a default value for (.*)
in Monoid
, then you can't.
foldr1
is defined in the Prelude as a non-typeclass function, so you can't give it a local definition in Semigroup
(.*)
is part of the Semigroup
class. You can give its values in Semigroup
instances, and you can give a default value for it in the Semigroup
class, but you can't give its value in the Monoid
class (or Monoid
instances)If you're trying to to provide a default value for (.*)
in Semigroup
, and a default value for identity
in Monoid
, then you're using the wrong syntax.
Instead try something like
class Semigroup a where
(.*) :: a -> a -> a
(.*) = {-something-}
or
class Semigroup a where
(.*) :: a -> a -> a
x .* y = {-something-}
Upvotes: 4