[Haskell-cafe] Re: Storing functional values
nickgrey at softhome.net
nickgrey at softhome.net
Mon Feb 2 16:26:23 EST 2004
Dylan Thurston writes:
> It seems like there are two things you want to do with these
> functional closures: save them to disk, and run them as functions.
> Why not combine these two into a type class?
Dylan,
This is the kind of thing I'd like to do, but I can't see how to do it.
(Not that I'm claiming it's impossible, I'd played with Haskell on and off
for a couple of years now, but I'm a long way from being an expert.)
class StoreableFunc1 a where
store :: a -> String
unstore :: String -> a
apply :: ?? -- What type here??
Probably a multi-parameter class would be appropriate, but again I can't
really see how:
class StorableFunc2 (f a) where
store :: f a -> String
unstore :: String -> f a
apply :: f (b -> c) -> b -> f c -- Would need a type roughly like this
-- But this is obviously wrong
Of course, I could do:
class StorableFunc3 (f a) where
store :: f a -> String
unstore :: String -> f a
unwrap :: f a -> a
But then, once you chose to apply one value a function, it is no longer
storable.
I have actually managed to hack something together which satisfies most of
my requirements. I have a type (ExtFunc a) which is an instance of Read and
Show. There are the following functions:
apply :: forall b a. (Show a) => ExtFunc (a -> b) -> a -> ExtFunc b
unwrap :: forall a. ExtFunc a -> a
So, ExtFuncs can be used just like functions, and can be shown and read,
even when partially applied, which I like. The Show a context on apply is
obviously because the argument has to be shown when showing a partially
applied value.
For example, TestTaggedFunc.test is a function which adds it's two
parameters.
*TaggedFunc> TestTaggedFunc.test 1 2
3
I've associated the tag "test" with the function test, so the string
"ExtFunc{test}" when read, produces the test function wrapped up in an
ExtFunc:
*TaggedFunc> let x = read "ExtFunc{test}" :: ExtFunc (Int -> Int -> Int)
*TaggedFunc> x
ExtFunc{test}
(Note that unwrap x is exactly TestTaggedFunc.test)
Can partially apply the function and it's still showable:
*TaggedFunc> let y = apply x 1
*TaggedFunc> y
ExtFunc{test 1}
Fully applying the function still shows the parameters:
*TaggedFunc> let z = apply y 2
*TaggedFunc> z
ExtFunc{test 1 2}
But we can unwrap the actual value:
*TaggedFunc> unwrap z
3
The main problem it that all the exported functions have to be collected
together in the module which has the instance of Read (ExtFunc a), meaning
that if a module wants to both export functions for use in ExtFunc and read
ExtFuncs, there is a mutual recursion.
It also uses Dynamic (to allow all the functions exported from all modules
to appear in a single list), so there's potential for types not to match up
etc, although I think this isn't much worse than the potential failure of
any read due to the type not matching the value in the string. (But I'm not
really sure because I've only just discovered the Dynamic module.)
Comments appreciated.
Regards,
Nick
More information about the Haskell-Cafe
mailing list