1
votes

I've got some, probabbly simple, trouble with typeclasses and creating instances from them. I'm trying to make a typeclass for some functions from the Haskell List and Set functions, like for example "size", "null", and "filter. I already got "size" and "null" working by using:

 module Main where

  import qualified Data.List as DL
  import qualified Data.Set as DS

  class Interface a where
      null' :: [a] -> Bool
      size' :: a -> Int

  instance Interface [a] where
      null' xs = DL.null xs
      size' xs = DL.length xs

  instance Interface (DS.Set a) where
      null' x = DS.null x
      size' x = DS.size x

This functions work as far as I tested it. Now I tried to implement the filter function with

class Interface a where
    null' :: [a] -> Bool
    size' :: a -> Int
    filter' :: (a-> Bool) -> a -> a

instance Interface [a] where
    null' xs = DL.null xs
    size' xs = DL.length xs
    filter' f xs = DL.filter f xs

The problem I got now is the following:

ue4.hs:17:30:
    Couldn't match type ‘a’ with ‘[a]’
      ‘a’ is a rigid type variable bound by
          the instance declaration at ue4.hs:14:10
    Expected type: a -> Bool
      Actual type: [a] -> Bool
    Relevant bindings include
      xs :: [a] (bound at ue4.hs:17:15)
      f :: [a] -> Bool (bound at ue4.hs:17:13)
      filter' :: ([a] -> Bool) -> [a] -> [a] (bound at ue4.hs:17:5)
    In the first argument of ‘filter’, namely ‘f’
    In the expression: filter f xs

As far as I understand, the Problem is within the Function. It needs to get an normal value, as to go over the map and evaluate the function with all values to put them in the resultlist which will be given back by the filter. But the [a] in the instance declaration reads everything as a list, which it shouldnt.

If I put

        filter' :: (a-> Bool) -> [a] -> [a]

into the class, I think I get the list filter to work, but then I get problems with the Set filter and the sense of the Typeclass is lost.

Does anyone have any idea on how to approach or how to fix this? What do I have to take as class definitions?

1

1 Answers

1
votes

I already got "size" and "null" working by using

Really? That looks like an error to me. The definition of null' is pretty wonky. For list, you have:

null' :: [[a]] -> Bool

For Set, you have:

null' :: [Set a] -> Bool

I'm positive that's not what you want.

Maybe something like this is more appropriate:

module Main where
import qualified Data.List as DL
import qualified Data.Set as DS

class Interface a where
  null' :: a x -> Bool
  size' :: a x -> Int
  filter' :: (x -> Bool) -> a x -> a x

instance Interface [] where
  null' = DL.null
  size' = DL.length
  filter' = DL.filter

instance Interface DS.Set where
  null' = DS.null
  size' = DS.size
  filter' = DS.filter

Note that I've changed your interface to apply to a higher-kinded type, so instead of [a] being an instance of your class, [] itself is an instance of your class. This may not be what you want, but it does let you implement map (but alas, not for Set).