将具有有效功能空间(如ML)的语言核心嵌入Haskell有多实际?
正如Moggi在20年前提出的那样,像ML这样的语言的有效功能空间将具有有效功能空间(如ML)的语言核心嵌入Haskell有多实际?,haskell,f#,ocaml,effects,monads,Haskell,F#,Ocaml,Effects,Monads,正如Moggi在20年前提出的那样,像ML这样的语言的有效功能空间->可以分解为标准的总功能空间=>加上一个强大的monadT,以捕捉效果 A->B分解为A=>(tb) 现在,Haskell支持monad,包括一个IO monad,它看起来足以满足ML中的效果,并且它有一个包含=>(但也包括部分函数)的函数空间。因此,我们应该能够通过这种分解将大量的ML片段翻译成Haskell。理论上我认为这是可行的 我的问题是这样的嵌入是否可行:是否有可能设计一个Haskell库,允许在Haskell中以与M
->
可以分解为标准的总功能空间=>
加上一个强大的monadT
,以捕捉效果
A->B
分解为A=>(tb)
现在,Haskell支持monad,包括一个IO monad,它看起来足以满足ML中的效果,并且它有一个包含=>(但也包括部分函数)的函数空间。因此,我们应该能够通过这种分解将大量的ML片段翻译成Haskell。理论上我认为这是可行的
我的问题是这样的嵌入是否可行:是否有可能设计一个Haskell库,允许在Haskell中以与ML不太远的风格进行编程?如果是这样的话,表现如何
我的“实用”标准是,通过嵌入,可以相对容易地将大量使用效果的现有ML代码转录到Haskell中,包括涉及高阶函数的复杂情况
为了使这一点具体化,下面是我自己通过嵌入来实现这种转录的尝试。主要功能是转录一些简单的ML代码,强制生成5个不同的变量名。我的版本没有直接使用分解,而是提升函数,以便它们评估其参数。main
之前的定义是一个包含提升原语的小型库。这是可行的,但有些方面并不完全令人满意
val
向计算中注入值时,语法噪音有点太大。拥有未升级版本的函数(如rdV
)将有助于实现这一点,但代价是需要定义这些函数varNum
这样的非值定义需要通过a->ma进行一元绑定
val=返回
ref=连接。liftM NEVIOREF
rdV=readIORef——未刷新,因此接受一个值
(!=)rx=do{rr IO Int
((.+),(.-)=(liftM2(+),liftM2(-)
(.:)::IO a->IO[a]->IO[a]
(.:)=liftM2(:)
showIO::Show a=>IO a->IO字符串
showIO=liftM show
main=do
瓦努姆
值“v.”(showIO(rdV varNum))
让gen=(=返回[]
nn->(新值$val()):(gen(值n.-val 1))
总务(val 5)
> P>是一种可能的方式,Sigfpe。它不覆盖LAMBDAS,但它似乎可以扩展到它们。 + 1问一个问题,我不够聪明,不能贡献你所发表的问题和答案的性质,如果你还没有考虑,你会考虑吗?@ CAMCCANN有趣的。我猜我一直在测试和发现T。hat Stack Overflow对于这类问题很有用(这个问题可能会超出极限,或者很难回答)。我在TCS网站上有些分歧:我通常不喜欢将理论与实践分开,也不喜欢“理论”一词.这个问题与monads有关,但我主要是问一些实际用途的问题。就个人而言,我可能更喜欢使用TCS标记。一般来说,我认为当没有明确的分界线时,将事物集中在一起,然后通过标记投影出子集是一个更好的模型。一些C编译器允许嵌入汇编程序,例如asm
in-有人用sml
在GHC中嵌入标准ML吗?这是我可以尝试使用的两种有趣的技术。这与我给出的代码中的想法类似(这并不奇怪,因为我和Andrzej Filinski在CMU一起学习过)。此外,我将这种嵌入归类为“理论上有效”,而不是“实践上有效”另外,我想我现在应该避免使用模板,看看在不破坏语法的情况下有什么好的嵌入是可能的。
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)