在Haskell中实现一种语言:多态函数的动态类型?

时间:2018-02-03 03:34:57

标签: haskell polymorphism dsl dynamic-typing

我正在编写一种使用Haskell作为宿主语言的编程语言。 (我的语言的解析器,语法,运行时等都是用Haskell编写的。)

根据PL中程序中的内容,在我的语言运行时,我想动态地将不同类型的Haskell函数(它们的类型在运行时已知)应用于不同类型的Haskell值,其类型在运行时已知。我希望以通用的方式应用这些函数,而不必考虑每种可能的类型。基本上我希望我的语言运行时的这部分在Haskell中动态输入。我也想为我的语言写一个类型检查器。

关于我如何做这些事情的任何建议?是否有任何用Haskell编写的语言的例子做类似的事情,我可以从中学习哪些方法?

一个复杂因素:Haskell函数和值需要在浮点数上是多态的,因为我将它们与Haskell自动存储库(https://hackage.haskell.org/package/ad)一起使用,这要求浮点数具有类型(浮动a => a)。

我尝试使用Haskell Data.Dynamic和Data.Typeable库来使函数和值动态化,因此我可以在运行时比较它们的类型并在类型匹配时应用函数,但Data.Dynamic似乎不允许多态要转换为动态的函数。文档甚至说明了这一点。我用谷歌搜索“Haskell多态函数动态”,但我没有看到解决这个限制的方法。

我宁愿不强制所有Haskell函数具有相同的输入/输出类型,我宁愿不必在sum类型中静态列出所有可能的类型。也许我可以使用某种通用的可应用类型类来解决应用函数问题?或者使用Template Haskell?这些选项中没有一个听起来超级吸引人。

1 个答案:

答案 0 :(得分:0)

如果不了解有关您的问题域的更多信息,很难回答这个问题,但这里有一种方法可行:

  1. 将您的类型和函数分组到模块中:查看您的应用程序是否处理Foo类型并具有一组操作它们的相应函数,以及Bar类型具有大部分不相交的类型功能。一个真实的例子可能是数值函数和字符串函数。有一些交叉,但大多数是具有不同功能的单独类型。尝试编写这些函数,以便所有FooBar参数都在最后,所以更喜欢f :: String -> Foo -> Foo而不是f :: Foo -> String -> Foo

  2. 创建联合类型FooBar = data Dfoo Foo | Dbar Bar并关联prisms _Foo_Bar

  3. 使用您在步骤2中定义的棱镜,编写一系列函数将FooBar函数提升为FooBar类型。

  4. 例如,

      elevate2 :: Prism' b a -> (a -> a -> a) -> b -> b -> Maybe b
      elevate2 prism f arg1 arg2 = f <$> arg1 ^? prism <*> arg2 ^? prism
    

    现在每个操作都是动态输入的;当应用于正确的参数时,您得到Just您的结果,并使用错误的参数获得Nothing。如果您愿意,可以返回Either而不是Maybe来获取有关出错的更多信息,但这需要在高程函数中使用更多机器。