Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use Multiparameter type classes in Haskell?

I would like to understand the differences between the following two definitions of a Collection type class.

With multiparameter typeclasses and functional dependencies (taken from here);

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies #-}

class Eq e => Collection c e | c -> e where
    insert :: c -> e -> c
    member :: c -> e -> Bool

instance Eq a => Collection [a] a where
    insert = flip (:)
    member = flip elem

With only a single type parameter;

class Collection c where
    insert :: Eq e => c e -> e -> c e
    member :: Eq e => c e -> e -> Bool

instance Collection [] where
    insert = flip (:)
    member = flip elem

Both seem to compile and work ok. Are there any practical differences between the two, or any reason to favour one approach over the other?

like image 454
knick Avatar asked Sep 11 '25 09:09

knick


1 Answers

A simple example where the Fundep version still works, but not the single-parameter one, is a Set container:

import qualified Data.Set as Set

instance (Ord e) => Collection (Set.Set e) e where
  insert = Set.insert
  member = flip Set.member

An instance to the other class doesn't work because you need an Ord constraint. Now, you could change the definitions to

class Collection c where
    insert :: Ord e => c e -> e -> c e
    member :: Ord e => c e -> e -> Bool

But for simpler containers like lists that would merely be a nuisance, you'd like to also store non-ord types there. For Hashmaps you need yet another constraint. It's no good making those global and required for any collection.

like image 105
leftaroundabout Avatar answered Sep 14 '25 00:09

leftaroundabout