12

こんな感じの関数が欲しい

readFunc :: String -> (Float -> Float)

このようなものを操作します

>(readFunc "sin") (pi/2)
>1.0

>(readFunc "(+2)") 3.0
>5.0

>(readFunc "(\x -> if x > 5.0 then 5.0 else x)") 2.0
>2.0

>(readFunc "(\x -> if x > 5.0 then 5.0 else x)") 7.0
>5.0

信じられないほど素朴なアプローチ (これは でコンパイルする必要があることに注意してください{-# LANGUAGE FlexibleContexts #-})

readFunc :: (Read (Float -> Float)) => String -> (Float -> Float)
readFunc s = read s

与える

No instance for (Read (Float -> Float)) ...

そのようなインスタンスは存在しないため、これは理にかなっています。Stringtoからのマップを書くことで入力文字列を文字ごとに解析できることは理解していますFloat -> Floatが、少なくとも prelude の最も一般的な関数を解析できるようにしたいと考えています。これを行う簡単な方法はありますか?

ヒントを使用した1つのソリューション

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 all the points that will appear in the domain
points (SDom a b c d) m = [(x, y)|x <- [a, a+m .. b], y <- [c, c+m .. d]]
points (Dom a b c d next) m = points next m ++ [(x, y)|x <- [a, a+m .. b], y <- [c, c+m .. d]]

readFunc = do
    putStrLn "Enter a 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 a mesh size"
    meshSize' <- getLine
    let meshSize = (read meshSize') :: Float 
    --
    putStrLn "Enter an 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 the actual values
    putStrLn $ show values 

    --the type is indeed [float]
    putStrLn $ show $ typeOf values 
4

1 に答える 1