Total newbie here, struggling.
I'm trying to define a type class for sets. For this case it would only require the definition of 'exists'. 'exists' would take a set and function on a set item, and return a boolean. How can I define that in Haskell?
Is the following even in the right direction? So there is the type class definition and an implementation of set with list, for which 'exists' returns true for now..
-- Set.hs --
class Set a b where
exists :: a -> (b -> Bool) -> Bool
-- ListSet.hs --
instance Set ListSet a where
exists a f = True
--
(result: Too many parameters for class `Set')
Haskell has three basic ways to declare a new type: The data declaration, which defines new data types. The type declaration for type synonyms, that is, alternative names for existing types. The newtype declaration, which defines new data types equivalent to existing ones.
The Data Keyword and Constructors In general, we define a new data type by using the data keyword, followed by the name of the type we're defining. The type has to begin with a capital letter to distinguish it from normal expression names. To start defining our type, we must provide a constructor.
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.
Within the Haskell language, there is no way to check whether a value has a certain type or whether a type is a member of a certain class. Haskell is not (quite) a proof verification system, so there's no way to prove, in Haskell code, that an instance declaration satisfies the specification of a class.
You can do it this way, with enough extensions. At the very least, you'll need multiple-parameter type classes. However, it will be very annoying to use: you'll need to specify explicit type signatures all over the place. One way to fix it is to introduce a functional dependency (using another extension):
class Set a b | a -> b where
exists :: a -> (b -> Bool) -> Bool
This says that if you know the type of the set, you know the type of the elements, too. However, there's a simpler way that works without any extensions:
class Set f where
exists :: f a -> (a -> Bool) -> Bool
Here, the type class ranges over higher-kinded types, which is a neat trick and hard to come up with on your own if you've never seen it before!
Daniel Wagner already gave perfect answer on what you are trying to do. I just want to add a point about your error - Too many parameters for class 'Set'
. This means that you didn't enable corresponding GHC extension - MultiParamTypeClasses
. You can do it by specifying special kind of comment at the top of your source file:
{-# LANGUAGE MultiParamTypeClasses #-}
--
-- Your source code here
--
Then you should be able to compile your code.
Another Haskell feature mentioned in Daniel's answer also requires enabling certain extension, namely FunctionalDependencies
(this is the weird .. | a -> b ..
thing inside type class declaration). You can enable multiple extensions at the same time using comma, like this:
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
Carl's comment mentions another extension, TypeFamilies
, which could also provide means for what you are trying to do (generic class of set types or other kind of collections). You can read about it here: http://www.haskell.org/haskellwiki/Type_families.
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