Avoid long tuple definitions in haskell -
for work hxt implemented following function:
-- | construction of 8 argument arrow 8-ary function. same -- implementation in @control.arrow.arrowlist.arr4@. arr8 :: arrowlist => (b1 -> b2 -> b3 -> b4 -> b5 -> b6 -> b7 -> b8 -> c) -> (b1, (b2, (b3, (b4, (b5, (b6, (b7, b8))))))) c arr8 f = arr ( \ ~(x1, ~(x2, ~(x3, ~(x4, ~(x5, ~(x6, ~(x7, x8))))))) -> f x1 x2 x3 x4 x5 x6 x7 x8 )
as mentioned in haddock comment above function arr8
takes 8-ary function , returns 8 argument arrow. use function this: (x1 &&& x2 &&& ... x8) >>> arr8 f
whereby x1
x8
arrows.
my question: there way avoid big tuple definition? there more elegant implementation of arr8
?
info: used same code schema in function arr4 (see source code of arr4)
this works, though depends on quite deep , fragile typeclass magic. requires change tuple structure bit more regular. in particular, should type-level linked list preferring (a, (b, (c, ())))
(a, (b, c))
.
{-# language typefamilies #-} import control.arrow -- need able refer functions presented tuples, generically. -- not possible in straightforward method, introduce type -- family recursively computes desired function type. in particular, -- can see -- -- fun (a, (b, ())) r ~ -> b -> r type family fun h r :: * type instance fun () r = r type instance fun (a, h) r = -> fun h r -- then, given our newfound function specification syntax we're in -- proper form give recursive typeclass definition of we're -- after. class zup tup zup :: fun tup r -> tup -> r instance zup () zup r () = r -- note recursive instance simple enough not require -- undecidableinstances, techniques do. isn't -- terrible thing, if ui used it's author of typeclass -- , instances ensure typechecking terminates. instance zup b => zup (a, b) zup f ~(a, b) = zup (f a) b arrtup :: (arrow a, zup b) => fun b c -> b c arrtup = arr . zup
and can do
> zup (+) (1, (2, ())) 3 > :t arrtup (+) arrtup (+) :: (num a1, arrow a, zup b n, fun n b c ~ (a1 -> a1 -> a1)) => b c > arrtup (+) (1, (2, ())) 3
if want define specific variants, they're arrtup
.
arr8 :: arrow arr => (a -> b -> c -> d -> e -> f -> g -> h -> r) -> arr (a, (b, (c, (d, (e, (f, (g, (h, ())))))))) r arr8 = arrtup
it's worth noting if define lazy uncurry
uncurryl :: (a -> b -> c) -> (a, b) -> c uncurryl f ~(a, b) = f b
then can write recursive branch of zup
in way illustrative what's going on here
instance zup b => zup (a, b) zup f = uncurryl (zup . f)
Comments
Post a Comment