text parsing - How can I parse a string to a function in Haskell? -


i want function looks

readfunc :: string -> (float -> float) 

which operates this

>(readfunc "sin") (pi/2) >1.0  >(readfunc "(+2)") 3.0 >5.0  >(readfunc "(\x -> if x > 5.0 5.0 else x)") 2.0 >2.0  >(readfunc "(\x -> if x > 5.0 5.0 else x)") 7.0 >5.0 

the incredibly naive approach (note must compiled {-# language flexiblecontexts #-})

readfunc :: (read (float -> float)) => string -> (float -> float) readfunc s = read s 

gives

no instance (read (float -> float)) ... 

which makes sense since no such instance exists. understand can parse input string character character writing map string float -> float want able parse @ least common functions prelude, , way more work want commit to. there easy way of doing this?

just 1 solution using hint

import language.haskell.interpreter hiding (typeof) import data.typeable (typeof)  data domain = dom float float float float domain             | sdom float float float float              deriving (show, read)  --gets points appear in domain points (sdom b c d) m = [(x, y)|x <- [a, a+m .. b], y <- [c, c+m .. d]] points (dom b c d next) m = points next m ++ [(x, y)|x <- [a, a+m .. b], y <- [c, c+m .. d]]  readfunc =     putstrln "enter domain (as dom x-min x-max y-min y-max subdomain, or, sdom x-min x-max y-min y-max)"     domain' <- getline     let domain = (read domain') :: domain     --     putstrln "enter mesh size"     meshsize' <- getline     let meshsize = (read meshsize') :: float      --     putstrln "enter initial value function (as f(x,y))"     func' <- getline     values' <- runinterpreter $ setimports["prelude"] >>                                 eval ("map (\\(x,y) -> " ++ func' ++ ")" ++ show (points domain meshsize))     let values = (\(right v) -> (read v)::([float])) values'      --the haskell expression being evaluated     putstrln $ ("map (\\(x,y) -> " ++ func' ++ ")" ++ show (points domain meshsize))       --prints actual values     putstrln $ show values       --the type indeed [float]     putstrln $ show $ typeof values  

you can use hint package, or plugins. i'll show former (partly because windows installation little broken in cabal doesn't share belief have c installed, cabal install plugins fails).

string -> function easy:

import language.haskell.interpreter  getf :: string -> io (either interpretererror (float -> float)) getf xs = runinterpreter $    setimports ["prelude"]    interpret xs (as :: float -> float) 

you may want add additional modules imports list. tests out

ghci> getf "sin" >>= \(right f) -> print $ f (3.1415927/2) 1.0 ghci> getf "(\\x -> if x > 5.0 5.0 else x)" >>= \(right f) -> print $ f 7 5.0 

(notice escaping of escape character \.)

error messages

as may have noticed, result wrapped in either data type. right f correct output, whereas left err gives interpretererror message, quite helpful:

ghci> getf "sinhh" >>= \(left err) -> print err wontcompile [ghcerror {errmsg = "not in scope: `sinhh'\nperhaps meant `sinh' (imported prelude)"}] 

example toy program

of course, can use either code deal this. let's make fake example respond. real 1 contain maths of program.

respond :: (float -> float) -> io () respond f =    -- insert cunning numerical method instead of    let result = f 5    print result 

a simple, one-try, unhelpful version of program be

main =     putstrln "enter function please:"    >> getline     >>= getf     >>= either print respond  

example sessions

ghci> main enter function please: \x -> x^2 + 4 29.0 
ghci> main enter function please: ln wontcompile [ghcerror {errmsg = "not in scope: `ln'"}] 

it type checking you:

ghci> main enter function please: (:"yo") wontcompile [ghcerror {errmsg = "couldn't match expected type `ghc.types.float'\n            actual type `ghc.types.char'"}] 

Comments

Popular posts from this blog

python - How to create a legend for 3D bar in matplotlib? -

java - Multi-Label Document Classification -

php - Dynamic url re-writing using htaccess -