我有一个类似以下的主要内容:
main :: IO ()
main = do
args <- getArgs
putStrLn $ functionName args
where
functionName args = "problem" ++ (filter (/= '"') $ show (args!!0))
我没有像现在这样把名称放到标准输出中,而是想调用函数。
我知道这个事实,我可以使用提示(如Haskell: how to evaluate a String like "1+2"中提到的那样),但我认为仅仅获得这个简单的函数名称会有点过分。
在当前阶段,如果该功能不存在,程序是否会崩溃无关紧要!
答案 0 :(得分:6)
如果不采取特殊措施来保护它们,函数的名称可能会在编译的Haskell程序中完全消失。
我建议你制作一张大型顶级地图:
import Data.Map ( Map )
import qualified Data.Map as Map
functions :: Map String (IO ())
functions = Map.fromList [("problem1", problem1), ...]
call :: String -> IO ()
call name =
case Map.lookup name of
Nothing -> fail $ name + " not found"
Just m -> m
main :: IO ()
main = do
args <- getArgs
call $ functionName args
where
functionName args = "problem" ++ (filter (/= '"') $ show (args!!0))
答案 1 :(得分:6)
如果你要这样做,你有几种方法,但到目前为止最简单的方法就是模式匹配
此方法要求您要调用的所有函数都具有相同的类型签名:
problem1 :: Int
problem1 = 1
problem2 :: Int
problem2 = 2
runFunc :: String -> Maybe Int
runFunc "problem1" = Just problem1
runFunc "problem2" = Just problem2
runFunc _ = Nothing
main = do
args <- getArgs
putStrLn $ runFunc $ functionName args
这需要您在每次添加新runFunc
时向problemN
添加一行,但这非常易于管理。
答案 2 :(得分:2)
您无法获得标识符的字符串表示形式,而不是没有花哨的非标准功能,因为编译后不会保留该信息。因此,您将不得不将这些函数名称写为字符串常量某处。
如果函数定义无论如何都在一个文件中,我建议使用数据类型和lambda来避免完全复制这些函数名称:
Data Problem = {
problemName :: String,
evalProblem :: IO () # Or whatever your problem function signatures are
}
problems = [Problem]
problems = [
Problem {
problemName = "problem1",
evalProblem = do ... # Insert code here
},
Problem
problemName = "problem2",
evalProblem = do ... # Insert code here
}
]
main :: IO ()
main = do
args <- getArgs
case find (\x -> problemName x == (args!!0)) problems of
Just x -> evalProblem x
Nothing -> # Handle error
修改:为了澄清,我要说的是,你有一个XY Problem的重要内容。