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
Post a Comment