type families - OCaml functors (parametrized modules) emulation in Haskell -



type families - OCaml functors (parametrized modules) emulation in Haskell -

is there recommended way utilize typeclasses emulate ocaml-like parametrized modules?

for instance, need module implements complex generic computation, may parmetrized different misc. types, functions, etc. more specific, allow kmeans implementation parametrized different types of values, vector types (list, unboxed vector, vector, tuple, etc), , distance calculation strategy.

for convenience, avoid crazy amount of intermediate types, want have computation polymorphic dataset class, contains required interfaces. tried utilize typefamilies avoid lot of typeclass parameters (that cause problems well):

{-# language multiparamtypeclasses , typefamilies , flexiblecontexts , flexibleinstances , emptydatadecls , functionaldependencies #-} module main import qualified data.list l import qualified data.vector v import qualified data.vector.unboxed u import distances -- contains instances euclid distance -- import distances.euclid e -- contains instances kulback-leibler "distance" -- import distances.kullback k class ( num (elem c) , ord (tlabel c) , withdistance (tvect c) (elem c) , withdistance (tboxtype c) (elem c) ) => dataset c type elem c :: * type tlabel c :: * type tvect c :: * -> * info tdisttype c :: * info tobservation c :: * info tboxtype c :: * -> * observations :: c -> [tobservation c] measurements :: tobservation c -> [elem c] label :: tobservation c -> tlabel c distance :: tboxtype c (elem c) -> tboxtype c (elem c) -> elem c distance = distance_ instance dataset () type elem () = float type tlabel () = int info tobservation () = tobservationunit [float] info tdisttype () type tvect () = v.vector info tboxtype () v = vectorbox (v.vector v) observations () = replicate 10 (tobservationunit [0,0,0,0]) measurements (tobservationunit xs) = xs label (tobservationunit _) = 111 kmeans :: ( floating (elem c) , dataset c ) => c -> [tobservation c] kmeans s = undefined -- here implementation labels = map label (observations s) www = l.map (v.fromlist.measurements) (observations s) zzz = l.zipwith distance_ www www wtf1 = l.foldl wtf2 0 (observations s) wtf2 acc xs = acc + l.sum (measurements xs) qq = v.fromlist [1,2,3 :: float] l = distance (vectorbox qq) (vectorbox qq) instance floating => withdistance (tboxtype ()) distance_ xs ys = undefined instance floating => withdistance v.vector distance_ xs ys = sqrt $ v.sum (v.zipwith (\x y -> (x+y)**2) xs ys)

this code somehow compiles , work, it's pretty ugly , hacky.

the kmeans should parametrized value type (number, float point number, anything), box type (vector,list,unboxed vector, tuple may be) , distance calculation strategy.

there types observation (that's type of sample provided user, there should lot of them, measurements contained in each observation).

so problems are:

1) if function not contains parametric types in it's signature, types not deduced

2) still no idea, how declare typeclass withdistance have different instances different distance type (euclid, kullback, else via phantom types).

right withdistance polymorphic box type , value type, if need different strategies, may set them in different modules , import required module. hack , non-typed approach, right?

all of may done pretty easy in ocaml is't modules. proper approach implement such things in haskell?

typeclasses typefamilies somehow similar parametric modules, work different. need that.

it case haskell lacks useful features found in *ml module systems. there ongoing effort extend haskell's module system: http://plv.mpi-sws.org/backpack/

but think can bit farther without ml modules. design follows god class anti-pattern , why anti-modular.

type class can useful if every type can have no more single instance of class. e.g. dataset () instance fixes type tvect () = v.vector , can't create similar instance tvect = u.vector.

you need start implementing kmeans function, generalize replacing concrete types type variables , constraining type variables type classes when needed.

here little example. @ first have non-general implementation:

kmeans :: int -> [(double,double)] -> [[(double,double)]] kmeans k points = ...

then generalize distance calculation strategy:

kmeans :: int -> ((double,double) -> (double,double) -> double) -> [(double,double)] -> [[(double,double)]] kmeans k distance points = ...

now can generalize type of points, requires introducing class capture properties of points used distance computation e.g. getting list of coordinates:

kmeans :: point p => int -> (p -> p -> coord p) -> [p] -> [[p]] kmeans k distance points = ... class num (coord p) => point p type coord p coords :: p -> [coord p] euclidiandistance :: (point p, floating (coord p)) => p -> p -> coord p euclidiandistance b = sum $ map (**2) $ zipwith (-) (coords a) (coords b)

now may wish create bit faster replacing lists vectors:

kmeans :: (point p, dataset vec p) => int -> (p -> p -> coord p) -> vec p -> [vec p] kmeans k distance points = ... class dataset vec p map :: ... foldl' :: ... instance unbox p => dataset u.vector p map = u.map foldl' = u.foldl'

and on.

suggested approach generalize various parts of algorithm , constrain parts little loosely coupled type classes (when required). bad style collect in single monolithic type class.

haskell type-families

Comments

Popular posts from this blog

xslt - DocBook 5 to PDF transform failing with error: "fo:flow" is missing child elements. Required content model: marker* -

mediawiki - How do I insert tables inside infoboxes on Wikia pages? -

Local Service User Logged into Windows -