根据Haskell中的用户输入在运行时编写函数

men*_*ics 7 haskell

假设我有各种简单签名的100个函数(从单态开始,但想使多态案例也起作用)a - > b(Int - > Int,Int - > String,String - > Double,MyType - > MyOtherType等)

假设我向用户显示了这些列表.用户选择一个.我显示了一个函数列表,其参数与所选函数的输出兼容.用户选择一个.

我现在怎么能组成这两个功能?一般情况是一系列的组合,但我认为这个简单的案例涵盖了我正在使用的问题.

我知道我可以尝试unsafeCoerce或Data.Dynamic,但我试图看看是否可以避免这种情况,而那些显然仅限于导致问题的单态类型.

我想也许某种程度上我可以创建所有功能的数据结构以及它们可以组成的内容,但我不确定.当包含多态情况时,似乎不可能.

Dan*_*ner 12

问题归结为:我怎样才能向编译器证明这个输入那个函数以及我正在使用该函数的输出所做一切都以合理的方式排列?有几个答案.

  • 告诉编译器"只相信我".使用unsafeCoerce.
  • 告诉编译器"我有点猜测,但我很确定我是对的 - 所以请检查我,但是在运行时,而不是在编译时." 使用Data.Dynamic.
  • 通过案例分析对类型ab函数类型进行证明a -> b.根据有多少选择,也有对ab,这可能是一个有点阻力.
  • 承认你正在为自己的小语言写一个翻译和打字检查器,并且做得很好.创建一个语法,编写一个小解析器,创建一个AST,进行类型检查和评估.GADTs可以帮助您充分利用GHC的类型检查,减​​少类型检查你所要做的(但偶尔增加键盘打字,你必须做的量)的量.

作为第三选择的一个例子,假设你有f :: Int -> String,g :: Double -> Bool,choice1 :: Int,choice2 :: Int,choice3 :: Int,和choice4 :: Double.你可以写这样的东西:

main = prompt "f or g" >>= \ans -> case ans of
    "f" -> prompt "1, 2, or 3" >>= \ans -> case ans of
        "1" -> doSomethingWithString (f choice1)
        "2" -> doSomethingWithString (f choice2)
        "3" -> doSomethingWithString (f choice3)
    "g" -> prompt "4 is your only choice" >>= \ans -> case ans of
        "4" -> doSomethingWithBool (g choice4)
Run Code Online (Sandbox Code Playgroud)

这种方法通常可以清理很多 - 例如,所有"f"案例都可能崩溃.