有没有办法链接函数,如withCString?

ivo*_*sir 12 continuations haskell function-composition continuation-passing

有没有办法链接功能withCString?我的意思是任何看起来像的功能f :: Foo -> (CFoo -> IO a) -> IO a.

例如,假设有一个功能 cFunc :: CString -> CFoo -> CBar -> IO ()

Usualy,我会做类似的事情:

haskellFunc string foo bar =
  withCString string $ \ cString ->
    withCFoo foo $ \ cFoo ->
      withCBar bar $ \ cBar ->
        cFunc cString cFoo cBar
Run Code Online (Sandbox Code Playgroud)

但我想做的事情如下:

haskellFunc = (withCString |.| withCFoo |.| withCBar) cFunc
Run Code Online (Sandbox Code Playgroud)

与一些合适的组合操作员|.|.

我正在编写带有大量C绑定的库,这个样板经常出现.难道我做错了什么?

Cac*_*tus 17

您可以使用Continuation applicative来编写这些a -> (b -> IO c) -> IO c函数:

import Control.Monad.Cont

haskellFunc :: String -> Foo -> Bar -> IO ()
haskellFunc string foo bar = flip runCont id $ 
    cFunc <$> 
      cont (withCString string) <*> 
      cont (withCFoo foo) <*> 
      cont (withCBar bar)
Run Code Online (Sandbox Code Playgroud)

或者使用一些额外的语法:

haskellFunc' :: String -> Foo -> Bar -> IO ()
haskellFunc' string foo bar = flip runCont id $
    cFunc <<$>> withCString string <<*>> withCFoo foo <<*>> withCBar bar
  where
    f <<$>> x = f <$> cont x
    f <<*>> x = f <*> cont x
Run Code Online (Sandbox Code Playgroud)

  • 认识到这只是伪装的"连续"的另一个好处是你可以免费获得其他好东西.例如,您需要这些CPS样式分配器的任意集合:您可以使用`sequence`,`traverse`或类似的方法同时获取列表或其他值集合. (2认同)
  • 你有没有考虑过某种无点形式?我注意到@ ivokosir的原始问题表明他们更喜欢无点的答案,尽管`Cont`很漂亮,但是`Applicative`代码仍然很有意义! (2认同)