Semigroup/Monoid/Group type class hierarchy in Haskell errors
I'm trying to create a "hierarchy" of algebraic type classes, as follows:
class Semigroup a where
(.*)开发者_如何学Go :: 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.
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).
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.
foldr1is defined in the Prelude as a non-typeclass function, so you can't give it a local definition inSemigroup(.*)is part of theSemigroupclass. You can give its values inSemigroupinstances, and you can give a default value for it in theSemigroupclass, but you can't give its value in theMonoidclass (orMonoidinstances)
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-}
加载中,请稍侯......
精彩评论