Container types

In a way, this is a step back from my previous question, but ... Can someone remind me why this is not working?

  class Container ce where
   empty :: c
   insert :: e -> c -> c

 instance Container [x] x where
   empty = []
   insert = (:)

 instance Container ByteString Word8 where
   empty = BIN.empty
   insert = BIN.cons

 instance Ord x => Container (Set x) x where
   empty = SET.empty
   insert = SET.insert

Obviously, if it were that simple, no one would bother to invent functional dependencies or related types. So what is the problem with the above?

+7
source share
1 answer

There is nothing to stop you from adding instance Container [Int] Int and instance Container [Int] Char , and when you request empty :: [Int] , the compiler does not know which instance it should come from.

"Ah, but I only have instance Container [Int] Int " you say. "And instance Container [Int] Char will be a mistake anyway."

But the compiler cannot know that in the future you will not add instance Container [Int] Char , and if you do, it is not allowed to break existing code.

So, we need a way to tell the compiler that

  • the first parameter Container uniquely defines the second parameter Container
  • if he sees different instances that differ only in the second type, which indicates an error

Enter the functional dependencies.

+10
source

All Articles