[Haskell-cafe] Data Type Inheritance ala OO - Inheritence -- howto best in Haskell ?

Evan Laforge qdunkan at gmail.com
Fri Jun 17 19:21:08 CEST 2011


> - u create a class "Y" to tackle the "zero" problem for different kinds of y
> vectors in a common way

Yes.

> - u create a "Signal" class for the Y- signal inheriting interfaces from y
> and Storable.Storable

I wouldn't say "inheriting".  It puts a restriction on 'y' saying that
it has to be in Storable as well.  That's unnecessary, but it saves me
from having to put the restriction in all the places I use 'y'.  I.e.,
the class below is not necessary, all it does is that instead of
typing 'Storable (X, y), Y y' I can simply type 'Signal y'.  So it's
like a type alias for classes, except a little awkward because you
need some bogus instances:

class (Storable.Storable (X, y), Y y) => Signal y

I don't know if it's a good idea or not, I just got tired of ugly signatures.

> Then u nest X and Y in a V.Vector - array and give it the type synonym
> SigVec.
> In all of this X and Y are ur types (or type synonyms) and y is a help
> variable.

Sorry, there's some missing context which might make this more
confusing.  In SignalBase, X is a type but y is a type variable.  Y is
a type class that constrains the type variable 'y' (it could be named
'a' or 'b' or anything else).

In SignalBase, 'at' has this signature:

at :: (Signal y) => X -> SigVec y -> y


Then in Signal, there is a concrete definition for 'y' called Y:

newtype Signal = Signal { sig_vec :: SignalBase.SigVec Y }
type X = SignalBase.X
type Y = Double
instance SignalBase.Signal Y

-- To make the bogus empty instance for Signal happy, I have its requirements:

instance Storable.Storable (X, Y) where
    sizeOf _ = Storable.sizeOf (undefined :: RealTime)
        + Storable.sizeOf (undefined :: Double)
    ... etc.

instance SignalBase.Y Y where
    zero_y = 0
    ...

-- Now the 'at' in this module looks like:

at :: X -> Signal -> Y
at x sig = SignalBase.at x (sig_vec sig)

I took out the phantom variable 'y' since that's orthogonal (though
it's useful if you want to have several different types that can
support the same operations).

> - I read using composite datatype using the "data" keyword makes code rather
> slow - is nesting better ? : e.g. "data Signal Double v.Vector"  versus
> "newtype (Double, v.Vector)

They're the same, a tuple is an indirection just like a two argument
'data'.  And another pointer to follow in the middle is probably not
going to make your code slow.  If space saving is very important, you
can eliminate it with the UNPACK pragma, but only think about that if
you're storing very large numbers of them.

> - which nesting structure is most efficient  - touples, lists, V.vector, ...

Depends.  The various unboxed vectors are efficient for memory and
large scale transformation, lists are efficient for manipulating the
front and are lazy on every single element and don't need Storable
instances.



More information about the Haskell-Cafe mailing list