I am trying to understand the semantics of Haskell’s type classes (TCs) from a model-theory point of view. It might difficult to give precise model theoretic semantics to type classes (see 1, and 2). I am aware that the primary purpose of TCs is to handle overloading effectively. However, TCs also provide a means of specification which is broadly similar to signatures in algebraic specification languages (e.g. CafeOBJ or Maude).
The intuition is that TCs are roughly analogous to loose specifications and the instances are analogous to implementations. With the caveat that the equations are definitional in Haskell, axiomatic properties cannot be expressed.
Some rough, but correct, correspondence will do for my current research question.
Given a parameterized class (class Stack x ...)
, we can instantiate the formal parameter x
with an actual parameter, say instance Stack [] =...
(see below) The signature of the class methods and their type constraints are mapped to the more concrete instance (ignoring default implementations for the moment).
The instance (Stack [])
could be regarded as a refinement of (Stack x)
specification, the container part is fixed with [], but the type of the elements is left open.
Are the model classes of (Stack x)
and (Stack [])
related by a reduct or forgetful functor from (Stack [])
to (Stack x)
?
Could I say (Stack [])
implements (Stack x)
?
Here is my attempt to relate models of TCs with models of their instances.
Models specified in TC = Set of models in instances
$\mathcal{Mod}(\Sigma_c,\epsilon_c,\delta_c) = \left\{\mathcal{Mod}_i(\Sigma_i,\epsilon_i,\delta_i)\right\}$
The mappings could be interpreted as:
$\Sigma_c \rightarrow \Sigma_i $ identity signature morphism
$\epsilon_c \rightarrow \epsilon_i $ No default equations, mapping is from $\emptyset$ of sentences to implementaions.
$\delta_c \rightarrow \delta_i $ empty data type to concrete data type.
I do not think that there is any relation between the set of instances ({model1,model2,..} where each model in represented by a Haskell instance)
Any feedback on this posting would be most welcome.
Regards,
Pat
[1] A mathematical (categorical) description of type classes
[2] http://lambda-the-ultimate.org/node/3215#comment-47273
module StackTypeClass where
newtype V2 a = V2 (a, a) deriving Show
-- Specification
class Stack s where
empty :: s a
push :: a -> s a -> s a
top :: s a -> a
pop :: s a -> s a
-- Implementation or refinement 1
instance Stack [] where
empty = []
push s xs = s:xs
top xs = head xs
pop xs = tail xs
-- Implementation or refinement 1
instance Stack (V2 ) where
empty = V2 (undefined,undefined)
push s (V2 (a,b)) = (V2 (s,b))
top (V2 t) = fst t
pop (V2 (a,b)) = (V2 (b,b))
{-
Tests
push (1::Int) (V2 ((6::Int),(1::Int)))
pop (push (7::Int) (V2 ((1::Int),(1::Int))))
top (V2 (6,5))
:t (empty::(V2 (a,a)))
:t (empty::([a])
-}