问题 Haskell中的函数序列化


有没有办法在Haskell中序列化(读/显示)函数?

举例来说:

:t (+1) 
(+1) :: Num a => a -> a

我希望能够有类似的东西:

read "(+1)" :: Num a => a -> a

不幸的是,这会引发错误:

Could not deduce (Read (a -> a)) arising from a use of `read'
from the context (Num a)
  bound by an expression type signature: Num a => a -> a
  at <interactive>:1:1-30
Possible fix:
  add (Read (a -> a)) to the context of
    an expression type signature: Num a => a -> a
  or add an instance declaration for (Read (a -> a))
In the expression: read "(+1)" :: Num a => a -> a
In an equation for `it': it = read "(+1)" :: Num a => a -> a

4305
2017-08-03 12:03


起源

这正是Lisp方言发光的一个领域。 - Alexandre C.
Haskell的早期变体 - 持久Haskell - 允许序列化函数。我不确定它是否曾公开发布,因为它依赖于圣安德鲁斯大学(苏格兰)开发的持久语言Napier88的技术。我没有仔细阅读,但最近的论文“走向云中的Haskell”似乎表明,在主线GHC中可能已开始为分布式编程序列化函数。 - stephen tetley
确实有关于ghc的序列化功能的工作,但它将是一种有限的类型。 - augustss


答案:


你可以使用类似的东西 插件 包在运行时读取代码。正如奥古斯特所说,显示是不可能的。

如何使用它的一个例子:

import System.Eval.Haskell

main = do
  mf <- eval "(+1) :: Int -> Int" []
  case mf of
    Just f -> print $ (f :: Int -> Int) 0
    _      -> putStrLn "Couldn't eval for some reason. :("

6
2017-08-03 12:29



你能提供一些代码示例吗? - Roskoto
在答案中添加了一个用法示例。 - valderman
还有Hint包,不知道差异是什么。 - gatoatigrado


它(通常)不可能显示一个函数,但如果您在运行时可以使用Haskell编译器,则原则上可以读取一个函数。


10
2017-08-03 12:21



你能提供一些代码示例吗? - Roskoto
代码示例?一个Haskell编译器? - augustss
这当然不是不可能的。您可以 show 原始源,任何编译器内部表示,或者最好是一些与机器无关的字节码。这可以使用以下方法再次传输和读入 dynamic-loader 要么 plugins 包。 ......我没有说它会很漂亮。 ...动态代码加载和Haskell是彼此的对立面。 - Evi1M4chine
好吧,任何将函数转换为字符串的Haskell函数都不能是纯粹的,因为这会破坏引用透明性。但是在IO monad中你可以创造一些东西,但它需要编译器/运行时支持。 - augustss