User-defined List instance

class, haskell, types

Solution

Rather than defining `List` a type class, define it as a constructor class:

class List l where
    head :: l a -> a
    tail :: l a -> l a                                        

data ConsList a = Nil | Cons a (ConsList a)

instance List ConsList where
    head Nil = error "Empty List"
    head (Cons h _) = h
    tail Nil = error "Empty List"
    tail (Cons _ t) = t

Alternatively, fix the element type (note: for your type `ConsList`, this requires flexible instances):

{-# LANGUAGE FlexibleInstances #-}

class List l where
    head :: l -> Int
    tail :: l -> l

data ConsList a = Nil | Cons a (ConsList a)

instance List (ConsList Int) where
    head Nil = error "Empty List"
    head (Cons h _) = h
    tail Nil = error "Empty List"
    tail (Cons _ t) = t

Finally, with type families you can do even more fancy stuff, but it really depends on your specific scenario if you should go that far (probably not):

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies      #-}

class List l where
    type Elt l
    head :: l -> Elt l
    tail :: l -> l

data ConsList a = Nil | Cons a (ConsList a)

instance List (ConsList Int) where
    type Elt (ConsList Int) = Int

    head Nil = error "Empty List"
    head (Cons h _) = h

    tail Nil = error "Empty List"
    tail (Cons _ t) = t

Problem

This is supposed to be really simple, but I cannot seem to get around it. Suppose I have my own List class, declaring `head` and `tail` in its interface. `List` is supposed to be what you expect, that is a collection of homogeneous items. Then, I want to create a `data` type implementing the `List` interface. The following code is what I came up with, but it does not work: how would you fix it? ``` class List l where head :: l -> a -- ERROR! How do I tell: given a list, return an element? tail :: l -> l data ConsList a = Nil | Cons a (ConsList a) instance List (ConsList Int) where head Nil = error "Empty List" head (Cons h _) = h tail Nil = error "Empty List" tail (Cons _ t) = t ``` Thanks in advance!

Original source