Is it possible to emulate a function with your own data type with some GHC extension? What I want to do is e.g.
(imaginary syntax)
data MyFunc = MyFunc String (Int->Int)
instance (Int->Int) MyFunc where
($) (MyFunc _ f) i = f i
inc = MyFunc "increment" (1+)
test = inc 1
I.e. data that carries some meta-information with it and can be pattern matched, but which can still be called like a regular function. Now, I know that I could define my own infix operator like $$ and call inc $$ 1, but being able to use the regular function call syntax would be very useful in embedded DSLs.
Yes, it can be done to a limited extent.
But first we’ll need
Let’s define
I’m adding more structure to your names so I can get nicer show support. 😉
Then lets define a class:
Now, consider the type:
The result type of
magicis either(a -> b)or aM a b.So it can be used as a member of
MyFunc. Now, this type is somewhat unsatisfying, because you can’t make instances dispatch on it, but it does mean thatworks just fine.
We can even make a rather nice way to show them. Even though we can’t use show on
MyFunc, we can define it forM.Then we can make a function we can apply to
M a b(and by extension anyMyFunc) to get out anM a b.and we can define a special combinator to show
MyFuncs:Then we can play. We can define compositions of
MyFuncs.And because I gave enough structure to the names, we even get correct parenthesization for more complicated compositions, without needless parentheses.
But remember, you won’t be able to define any instances for
MyFunc, since it can only be atype, and not anewtype. In order to define instances you’ll have to define them onM, and then usemto convert to that type so that implicit dispatch has a type to grab onto.Because of the rank 2 type, if you use these heavily in local contexts, you may also want to turn on
NoMonoLocalBindsand/orNoMonomorphismRestriction.