Reputation: 29
Specifically, inspired by J's conjucation operator (g&.f = (f inverse)(g)(f)) I need a way to augment functions with additional information. The obvious way is to use ADT. Something like:
data Isomorphism a b = ISO {FW (a -> b) , BW (b -> a)}
(FW f) `isoApp` x = f x
(BW g) `isoApp` x = g x
But the need for an application function really hurts code readability when most of the time you just want the forward function. What would be very useful is a class:
class Applyable a b c | a b -> c where
apply :: a -> b -> c
(I think the b could be made implicit with existential quantifiers but I'm not comfortable enough to be sure I wouldn't get the signature wrong)
Now the apply would be made implicit so you could just write
f x
as you would any other function. Ex:
instance Applyable (a -> b) a b where
apply f x = f x
instance Applyable (Isomorphism a b) a b where
apply f x = (FW f) x
inverse (Iso f g) = Iso g f
then you could write something like:
conjugate :: (Applyable g b b) => g -> Iso a b -> b -> a
f `conjugate` g = (inverse f) . g . f
Ideally the type signature could be inferred
However, these semantics seem complicated, as you would also need to modify (.) to support Applyable rather than functions. Is there any way to simply trick the type system into treating Applyable datatypes as functions for all normal purposes? Is there a fundamental reason that this is impossible / a bad idea?
Upvotes: 0
Views: 107
Reputation: 62868
As far as I know, function application is possibly the one thing in the entire Haskell language that you cannot override.
You can, however, devise some sort of operator for this. Admittedly f # x
isn't quite as nice as f x
, but it's better than f `isoApp` x
.
Upvotes: 2