RD1*_*RD1 16 monads f# ocaml haskell effects
正如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是一个小型图书馆,包括解除原语.这项工作没问题,但有些方面并不完全令人满意.
val.具有功能(如未提升的版本rdV),将有助于这一点,在这些要求中定义的成本.varNum需要monadic绑定通过<-a do.然后,这会强制任何依赖于它们的定义也在同一个do表达式中.do表达.这是ML程序是如何经常考虑,但在Haskell它不是那么很好的支持-例如,你不得不使用case,而不是公式.那么,有关改进这一点的建议,或者使用相同分解的更好方法,甚至是使用反映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)
Run Code Online (Sandbox Code Playgroud)