将具有有效功能空间(如ML)的语言核心嵌入Haskell有多实际?

将具有有效功能空间(如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

正如Moggi在20年前提出的那样,像ML这样的语言的有效功能空间
->
可以分解为标准的总功能空间
=>
加上一个强大的monad
T
,以捕捉效果

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)