
On 14 October 2010 08:34, Jacek Generowicz
Those other data might be the functions' arguments, or they might be other functions with which they are to be combined, or both.
You can represent these as existential packages. However, as Oleg shows you can always use skolemisation to eliminate the existential: http://okmij.org/ftp/Computation/Existentials.html This trick is basically what Brandon and Evan pointed out earlier when they suggested you replace the list :: [exists b. (b -> a, b)] with a list :: [a].
Here's an example where lazy evaluation isn't enough:
def memoize(fn): cache = {} def memoized_fn(*args): if args not in cache: cache[args] = fn(*args) return cache[args] return memoized_fn
You memoize a function once, but it will be given different arguments, many times, at a later time.
I'm not sure why you would use existentials for this. Isn't the type of memoized_fn just :: Ord a => (a -> b) -> a -> b? This doesn't deal with argument *lists* so you may have to curry/uncurry to get functions of a different arity to go through, but that is IMHO a reasonable requirement for Haskell, where multi-argument functions do not have special status. (In the absence of side effects, I can't see an obvious way to implement it without some way to enumerate the domain "a" though. Conal Elliot uses type classes to solve this issue, see http://hackage.haskell.org/package/MemoTrie, where memo :: HasTrie t => (t -> a) -> t -> a).
will do. So please allow me to store (fnA1, fnA2) and (fnB1, fnB2) in the same place. The program can tell that it can combine them with (.) because the type of
But if the only operation you ever do on this pair is (.), you may as well skolemise and just store (fnA1 . fnA2) directly. What is the advantage of doing otherwise? Max