0

I have a strange question in relation to type classes. So you can define a basic type class like this:

class Property x where
    checkThing :: x -> Int -> Bool
    transformThing :: x -> x

If you want to have a type class with multiple parameters you can enable:

{-# LANGUAGE MultiParamTypeClasses #-}

This will let you do things like:

class Property x y where
    checkThing :: x -> Int -> Bool
    transformThing :: x -> y -> Int

Here is my problem: So imagine I wanted to write a type class for automata (The kind that accept a language). I would write a type class that looked something like this:

class Automata machine where
    isDeterministic :: machine -> Bool
    acceptsInput :: machine -> String -> Bool

A automata takes in an input and decides if that input is part of a language. The above class would work for this. But wait this is limited to lists of characters (String) what if I want to generalize by Automata? Well I could add another variable to my class definition:

class Automata machine alphabet where
    isDeterministic :: machine -> Bool
    acceptsInput :: machine -> [alphabet] -> Bool

Hmm that is okay. But alphabet may have no direct relation to machine. Im in luck though! I can enable:

{-# LANGUAGE FunctionalDependencies #-}

And force language to depend on machine

class Automata machine alphabet | machine -> alphabet where

Ok now when I make an instance of Automata I can require alphabet to be related to the machine. For example:

instance Automata (FSM alphabet) alphabet where

works, and this correctly

instance Automata (FSM alphabet) othertypevariable where

gives an error. This is ok but not very generic. For example I have to define an instance for every type of automata, and every type of alphabet they can take. Thats horrible. In addition the functional dependencies does not actually force a relation. You can write:

 instance Automata (FSM alphabet) Int where

without a compiler error. Here is what would be ideal.

class Automata (machine alphabet) where
    isDeterministic :: machine alphabet -> Bool
    acceptsInput :: machine alphabet -> [alphabet] -> Bool

If I could specify a particular type parameter on the data instances are being defined for. For example the data that automata could be defined for would look like:

data FSM alphabet = FSM [alphabet]

or something like that. This would also allow defining single generic instances such as:

instance Automata (FSM alphabet) where

These examples are a simplified version I am trying to do but a solution for this problem would solve my problem. How could I go about expressing something this? Can I bend type classes to my will? Language extensions are acceptable.

44701
  • 397
  • 4
  • 10
  • n.m.'s answer is correct, but your reason why you're not satisfied with the functional-dependency approach doesn't make sense to me. – leftaroundabout Feb 28 '16 at 12:11

1 Answers1

5

Haskell type classes can abstract over arbitrary kinds. This means parameters o type classes can themselves have parameters. Familiar examples include Functor and Monad, that accept arguments like [] or Maybe. Here's a way to write write it with a type of *→* kind:

class Automata machine where
    isDeterministic :: machine alphabet -> Bool
    acceptsInput :: machine alphabet -> [alphabet] -> Bool

data FSM alphabet = FSM [alphabet] -- just an example, you need more 
                                   -- stuff to define a real FSM...

instance Automata FSM where 
    ...

Using {-# LANGUAGE KindSignatures #-} the kind of machine can be made explicit:

class Automata (machine :: * -> *) where
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • 2
    Perhaps you mean that classes can abstract over arbitrary kinds, which is the correct foil to concrete types. Type constructors are the foil to arbitrary type-level terms. e.g. `Bool`, `Maybe`, and `State` are type constructors, but `State s` -- though it is not a concrete type and has a higher kind -- is _not_ a type constructor. – Daniel Wagner Feb 27 '16 at 02:29
  • @DanielWagner You can call it a type constructor expression. See [the article that started it all](http://www.cs.tufts.edu/comp/150GIT/archive/mark-jones/fpca93.pdf) (pdf). But maybe you are right and this is an outdated term. – n. m. could be an AI Feb 27 '16 at 07:01