正如 Moggi 20 年前提出的,有效函数空间 ->
像 ML 这样的语言可以分解为标准的总函数空间 =>
加上一个强大的单子(monad)T
捕捉效果。A -> B
分解为 A => (T B)
现在,Haskell 支持 monad,包括一个 IO monad,它看起来足以满足 ML 中的效果,它有一个包含 => 的函数空间(但也包括部分函数)。因此,我们应该能够通过这种分解将 ML 的相当一部分片段转换为 Haskell。从理论上讲,我认为这是可行的。
我的问题是这样的嵌入是否可行:是否有可能设计一个 Haskell 库,允许在 Haskell 中以离 ML 不远的风格进行编程?如果是这样,性能将如何?
我对“实用”的标准是,现有的具有广泛使用效果的 ML 代码可以通过嵌入相对容易地转录成 Haskell,包括涉及高阶函数的复杂案例。
为了具体说明这一点,我自己尝试通过嵌入进行这样的转录如下。主要功能是一些简单的 ML 代码的转录,这些代码命令式地生成 5 个不同的变量名称。我的版本不是直接使用分解,而是提升函数,以便它们评估它们的参数 - main
之前的定义是一个包含提升原语的迷你库。这工作正常,但某些方面并不完全令人满意。
val
将值注入(inject)到计算中的语法噪音有点过大。 .拥有未提升版本的函数(如 rdV
)将对此有所帮助,但代价是需要定义这些函数。 varNum
需要通过 <-
进行单子(monad)绑定(bind)在 do
.然后,这会强制任何依赖于它们的定义也位于相同的 do
中。表达。 do
。表达。这就是机器学习程序经常被考虑的方式,但在 Haskell 中它并没有得到很好的支持——例如,你被迫使用 case
而不是方程。 那么,关于改进这一点,或者关于使用相同分解的更好方法,甚至是使用反射(reflect) ML 的风格在 Haskell 中实现相同广泛编程目标的完全不同方法的任何建议?
(并不是我不喜欢 Haskell 的风格,只是我希望能够轻松地映射现有的 ML 代码。)
import Data.IORef
import Control.Monad
val :: Monad m => a -> m a
val = return
ref = join . liftM newIORef
rdV = readIORef -- Unlifted, hence takes a value
(!=) r x = do { rr <- r; xx <- x; writeIORef rr xx }
(.+),(.-) :: IO Int -> IO Int -> IO Int
( (.+),(.-) ) = ( liftM2(+), liftM2(-) )
(.:) :: IO a -> IO [a] -> IO [a]
(.:) = liftM2(:)
showIO :: Show a => IO a -> IO String
showIO = liftM show
main = do
varNum <- ref (val 0)
let newVar = (=<<) $ \() -> val varNum != (rdV varNum .+ val 1) >>
val 'v' .: (showIO (rdV varNum))
let gen = (=<<) $ \n -> case n of 0 -> return []
nn -> (newVar $ val ()) .: (gen (val n .- val 1))
gen (val 5)
最佳答案
Here是一种可能的方式,通过 sigfpe。它不包括 lambda,但似乎可以扩展到它们。
关于haskell - 将具有有效功能空间(如 ML)的语言核心嵌入到 Haskell 中有多实用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3407401/