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

时间:2010-08-04 15:59:42

标签: haskell f# ocaml effects monads

正如Moggi 20年前提出的那样,像ML这样的语言的有效函数空间->可以分解为标准的总函数空间=>加上强大的monad T来捕获效果。

A -> B分解为A => (T B)

现在,Haskell支持monad,包括一个看起来足以满足ML效果的IO monad,它有一个包含=>的函数空间。 (但也包括部分功能)。因此,我们应该能够通过这种分解将相当大的ML片段转换为Haskell。从理论上讲,我认为这是有效的。

我的问题是这样的嵌入是否可行:是否有可能设计一个Haskell库,允许在Haskell中以不太远的ML的方式编程?如果是这样,性能如何呢?

我对“实际”的标准是,现有的广泛使用效果的ML代码可以通过嵌入相对容易地转录到Haskell中,包括涉及高阶函数的复杂情况。

为了使这个具体化,我自己尝试通过嵌入这样的转录是在下面。主要功能是转录一些简单的ML代码,强制生成5个不同的变量名。我的版本不是直接使用分解,而是提升函数以便评估它们的参数 - main之前的定义是一个包含提升原语的迷你库。这没关系,但有些方面并不完全令人满意。

  1. 通过val将值注入到计算中会有太多的语法噪音。拥有未提升的函数版本(如rdV)会有所帮助,但需要定义这些函数。
  2. varNum等非值定义要求<-中的do进行一元绑定。然后,这会强制任何依赖于它们的定义也在同一个do表达式中。
  3. 似乎整个程序最终可能会出现在一个巨大的do表达式中。这就是ML程序经常被考虑的方式,但在Haskell中它并没有得到很好的支持 - 例如,你被迫使用case代替方程式。
  4. 我想尽管穿过IO monad,但仍会有一些懒惰。鉴于ML计划将被设计用于严格评估,可能应该删除懒惰。我不确定最好的方法是做什么。
  5. 那么,有关改进这一点的建议,或使用相同分解的更好方法,甚至是使用反映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)
    

1 个答案:

答案 0 :(得分:3)

通过sigfpe可能的方式{p> Here。它不包括lambdas,但它似乎可以扩展到它们。