1

Is there a function in Haskell standard library (or some other modules / packages) that can take a String literal such as "+", "head" etc., then turn those into their corresponding Haskell functions, such as +, head ?

Hoogle did not produce any immediately useful answers. A dummy example for such a function would work like this:

eval :: String -> (a -> b)
eval "+" = (+)
eval "head" = head

p.s. Given that "corresponding" here can mean different things under different context (+ may no longer be defined as numeric addition for types that are not Numbers) but is necessary to answer this question, let's assume that the "corresponding" function for a string is the function that type checks and could be evaluated in the environment where the string is being turned into this function, a.k.a. use the lexical scope to lookup the value of this function.

If there is no such function, is there a deep reason (e.g. from lambda calculus, type theory etc.) why, and is it impossible to implement in any strict static typed language? If it is impossible in Haskell, what is actually a recommended practice to problems such as this? Imagine implementing a linear algebra library where strings either eval into functions that create values (e.g. vect2 is a function that creates a two dimensional function), or (binary, for simplicity) operations that map from them unto some other type (we could optionally provide type annotations for these, such as eval "innerProduct" :: Double, eval "matrixProduct" :: Matrix etc.)

More generally, a String type has a kind *, but a function -> has a kind * -> * -> *. Assuming that we can provide the first two kinds * from the lexical scope, it should be possible, right?

duplode
  • 33,731
  • 7
  • 79
  • 150
hyiltiz
  • 1,158
  • 14
  • 25
  • 1
    Related: [*How to serialize function type to json in haskell?*](http://stackoverflow.com/q/42701878/2751851) – duplode Apr 14 '17 at 18:50
  • You might like [dyre](http://hackage.haskell.org/package/dyre), which lets you invert control: rather than your program taking a string and evaluating it as Haskell, you write some Haskell that uses things exposed in your library (and dyre handles the job of handing off to GHC when the "string" changes). There is also of course the GHC API and things built on top of them like [hint](http://hackage.haskell.org/package/hint) and [mueval](http://hackage.haskell.org/package/mueval). – Daniel Wagner Apr 14 '17 at 20:56

2 Answers2

7

If I have a function

eval :: String -> (a -> b)

Then, the following code type checks:

foo :: Int -> Int -> Int
foo = eval "(+)"

bar :: Char -> Bool
bar = eval "(+)"

There's clearly something wrong. What you want, to start, is to quantify a and b existentially instead of universally.

data Fun where
   Fun :: (a -> b) -> Fun

eval :: String -> Fun

However, a value in such existential type would be unusable for anything else. Given a Fun and, say, a string, you can't apply the function to the string because the function might require a boolean input, for what we know.

A more sensible option could be using Typeable.

eval :: (Typeable a, Typeable b) => String -> Maybe (a -> b)

this could return Nothing when the string does not type check against the chosen a and b, while parsing the string and evaluating it to a function of the right types otherwise.

(By the way, why the result of such eval should be constrained to a function? It seems pointless to do so.)

This is, in principle, achievable. The libraries in fact contain System.Eval.Haskell.eval to a similar aim.

However, unless you really want to write a program which receives Haskell code at runtime and interprets it, I strongly recommend you avoid anything like eval. Using it for ordinary programming seems to grossly violate the spirit of the language, its idioms, and to possibly circumvent the static guarantees offered by the type system, turning compile time errors into runtime.

While I am no expert, I think using eval in scripting languages is mostly considered a very bad design.

TL;DR. It is probably a very bad idea to use eval for anything which does not strictly require eval. Avoid it.

chi
  • 111,837
  • 3
  • 133
  • 218
  • 1
    It'd be nice if it were possible to write `eval :: Typeable a => String -> Maybe a` without the `IO` wrapper and without GHC overwriting signal handlers (which I think is the only side effect of things like `eval`). – Cirdec Apr 14 '17 at 19:31
  • @Cirdec Can you elaborate a bit on the IO wrapper and "GHC overwriting signal handlers"? Seems interesting. – hyiltiz Apr 14 '17 at 19:35
  • @chi I understand that using `eval` to actually evaluating something (random) string is a very bad idea, but not sure why turning strings into values / functions would be a bad idea. – hyiltiz Apr 14 '17 at 19:36
  • @hyiltiz To turn strings into first-order values we have `read`. For functions, it depends on what are you trying to achieve. If you are writing an interpreter, that's ok. If your strings, say, can only be `(*)` and `(+)`, using eval is overkill, and potentially dangerous. Again, as I wrote above, why would one circumvent the static type system? I program in statically typed languages to detect errors early, `eval` turns compile time errors into runtime one, which is very bad to me -- the whole philosophy of Haskell is going the other way – chi Apr 14 '17 at 20:09
  • @Cirdec It would also require your runtime to include a copy of the GHC compiler! The `IO` constraint present in e.g. `hint` is because it starts a copy of the GHC process through system commands and interacts with that new process through a pipe. – user2407038 Apr 15 '17 at 14:41
4

No, there is no such function.

Rein Henrichs
  • 15,437
  • 1
  • 45
  • 55
  • Question edited with more information about context and "correspondence". – hyiltiz Apr 14 '17 at 19:00
  • 3
    @hyiltiz: well, there is such a function. It's called "compiler" ;). – Zeta Apr 14 '17 at 19:09
  • @Zeta The compiler can/will do part of that. However, it also (lazily, in Haskell's case) evaluates the functions. I am not asking for evaluating the function (yet), just turning the string into a function. – hyiltiz Apr 14 '17 at 19:13
  • 2
    @hyiltiz No, the compiler generally does not run the programs it produces. What makes you say that it does ("the compiler also evaluates the functions")? – Daniel Wagner Apr 14 '17 at 20:54
  • @hylitiz the compiler does *not* 'evaluate functions'. Lazy evaluation is done via thunks, and certainly not by the compiler during runtime. Haskell is not a scripting language, so no such function exists. – AJF Apr 14 '17 at 23:22