Haskell pattern match on tuple length in instances -
i want create data type can take tuple, of either length 2 or 3, , should contain types deriving num , ord. then, want pattern match on length of tuple in type class instances can decide function use based on tuple length. take @ non-compilable, pseudo-code below. there @ least 2 problems:
dominates
not derivable classi don't know how tuple, e.g. call
fitnesses
, variable out of data type when pattern matching in instance.
code:
data fits = i2 (int, int) | f2 (float, float) | i3 (int, int, int) | f3 (float, float, float) data ind = ind { fitnesses :: fits , otherinfo :: string } deriving (dominates) class dominates dominates :: -> -> bool instance dominates ind dominates x@(_,_) y@(_,_) = x `dominates2` y -- takes 2 tuples of length 2 dominates x@(_,_,_) y@(_,_,_) = x `dominates3` y -- takes 2 tuples of length 3
update:
data ind = ind { fitnesses :: fits , otherinfo :: string } instance eq ind (ind{ fitnesses = i2 x@(a1,a2) }) == (ind{ fitnesses = i2 y@(b1,b2) }) = indcmp2 x y == eq instance ord ind (ind{ fitnesses = i2 x@(a1,a2) }) `compare` (ind{ fitnesses = i2 y@(b1,b2) }) = indcmp2 x y indcmp2 :: (num a, ord a) => (a, a) -> (a, a) -> ordering indcmp2 x y | a0 < b0 = lt | a0 > b0 = gt -- can assume (fst x) == (fst y) beneath | a1 < b1 = lt | a1 > b1 = gt | a1 == b1 = eq a0 = fst x a1 = snd x b0 = fst y b1 = snd y
this compiles. why necessary make instance of eq
, if want ord
? without eq-instance compiler complains "no instance (eq ind)".
you can provide instances 2- , 3-tuples.
class dominates dominates :: -> -> bool instance (num a, num b) => dominates (a,b) dominates = dominates2 -- takes 2 tuples of length 2 instance (num a, num b, num c) => dominates (a,b,c) dominates = dominates3 -- takes 2 tuples of length 3
i wonder, however, if need.
you instead need pattern match on possible cases follows. no classes needed here.
dominates :: ind -> ind -> bool dominates (ind{ fitnesses = i2 (a1,a2) }) (ind{ fitnesses = i2 (b1,b2) }) = ... dominates (ind{ fitnesses = f2 (a1,a2) }) (ind{ fitnesses = f2 (b1,b2) }) = ... dominates (ind{ fitnesses = i3 (a1,a2,a3) }) (ind{ fitnesses = i3 (b1,b2,b3) }) = ... dominates (ind{ fitnesses = f3 (a1,a2,a3) }) (ind{ fitnesses = f3 (b1,b2,b3) }) = ... dominates _ _ = error "incompatible ind values!"
example:
data ind = ind { fitnesses :: fits , otherinfo :: string } -- no deriving ord here, want define manually instance ord ind (ind{ fitnesses = i2 x }) `compare` (ind{ fitnesses = i2 y }) = indcmp2 x y -- other cases here
Comments
Post a Comment