John Fouhy wrote:
> [...]
> data Thing = Thing { field_one :: String, field_two :: String,
> field_three :: Integer }
>
> type BooleanOp a = a -> a -> Bool
> type Field a = Thing -> a
>
> data ThingCompare a = TC (BooleanOp a) (Field a)
> | And (ThingCompare a) (ThingCompare a)
> | Or (ThingCompare a) (ThingCompare a)
> [...]
> tcEqOne = TC (==) field_one
> tcEqTwo = TC (==) field_two
> tcGtThree = TC (>) field_three
I'm not quite sure what you want to do with explicitly represented
comparisons. Maybe optimize them afterwards? Otherwise, BoolOp is likely
to be your best comparison representation.
You can separate the Field and the BoolOp parts with a small combinator
by :: BoolOp a -> (b -> a) -> BoolOp b
by f g x y = f (g x) (g y)
Then, the three comparisons become
tcEqOne = (==) `by` field_one
tcEqTwo = (==) `by` field_two
tcGtThree = (>) `by` field_three
Appealing to the famous instance Monad ((->) a), you can also say
and, or :: BoolOp a -> BoolOp a -> BoolOp a
and = liftM2 $ liftM2 (&&)
or = liftM2 $ liftM2 (||)
Regards,
apfelmus
_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe