
2010/1/27 Andrew U. Frank
dotoBfield :: (b -> b) -> X a b c -> X a b c dotoBfield op x = x { bfield = op (bfield x)}
and similar for A and C.
is there a better idiom to achieve the same effect? can this be automated (for example, using generics)?
Hello Andrew I use a family of variations on the S combinator (also known as Starling). I wouldn't argue its a better idiom, but I find it pleasantly regular. Suppose I had a data type for source positions like Parsec:
data SrcPos = SrcPos { src_line :: Int, src_column :: Int, src_tab_stop :: Int }
Then update functions on the record follow this pattern pstar<n> <update-function> (one-or more <selection-function>)
incrCol :: SrcPos -> SrcPos incrCol = pstar (\i s -> s { src_column=i+1 }) src_column
incrTab :: SrcPos -> SrcPos incrTab = pstar2 (\i t s -> s { src_column= (i+t) }) src_column src_tab_stop
incrLine :: SrcPos -> SrcPos incrLine = pstar (\i s -> s { src_line =i+1, src_column=1 }) src_line
At the moment I call the function family 'pstar' for permutated starlings, but in combinatory logic terms I don't think its strictly true to consider them permutations so they really need a new name. Here are the definitions, the order of arguments is changed from starlings to allow them to be generalized to functors should I need more generality:
pstar :: (a -> r -> ans) -> (r -> a) -> r -> ans pstar f fa x = f (fa x) x
pstar2 :: (a -> b -> r -> ans) -> (r -> a) -> (r -> b) -> r -> ans pstar2 f fa fb x = f (fa x) (fb x) x
pstar3 :: (a -> b -> c -> r -> ans) -> (r -> a) -> (r -> b) -> (r -> c) -> r -> ans pstar3 f fa fb fc x = f (fa x) (fb x) (fc x) x
pstar4 :: (a -> b -> c -> d -> r -> ans) -> (r -> a) -> (r -> b) -> (r -> c) -> (r -> d) -> r -> ans pstar4 f fa fb fc fd x = f (fa x) (fb x) (fc x) (fd x) x
pstar5 :: (a -> b -> c -> d -> e -> r -> ans) -> (r -> a) -> (r -> b) -> (r -> c) -> (r -> d) -> (r -> e) -> r -> ans pstar5 f fa fb fc fd fe x = f (fa x) (fb x) (fc x) (fd x) (fe x) x
Best wishes Stephen