如何在Haskell中实现此功能

men*_*ics 8 haskell

关于Haskell的精彩之处.函数的类型几乎决定了它的实现.对于这一个就是这种情况,但是......我的大脑并没有在这里包围嵌套函数:

mkDyn :: (Typeable a) => ((a -> IO()) -> IO ()) -> ((Dynamic -> IO()) -> IO ())
Run Code Online (Sandbox Code Playgroud)

唯一的问题是如何处理将要求的fromDynamic调用中的错误处理,但是......一旦我完成了其余的事情,我就可以处理它.我猜想在某个地方需要有类似的东西.但我似乎无法得到包装器lambda的东西.

case fromDynamic x of
  Just x -> f x
  Nothing -> undefined -- TODO 
Run Code Online (Sandbox Code Playgroud)

nom*_*olo 10

我想你想要的toDyn不是fromDynamic.所以让我们慢慢来:

mkDyn :: Typeable a =>
         ((a -> IO ()) -> IO ())
      -> (Dynamic -> IO ())
      -> IO ()
mkDyn k f = ...
Run Code Online (Sandbox Code Playgroud)

我们的返回类型应该是IO (),我们可以通过调用k或获取f.呼叫f对我们没有多大帮助,因为我们会以某种方式实现a Dynamic,但我们不能(明智地)做到这一点k.所以我们想打电话k. k需要另一个函数作为参数,所以让我们这样开始:

mkDyn k f = k (\a -> ...)
Run Code Online (Sandbox Code Playgroud)

所以函数的论点是Typeable a => a -> IO ().我们没有该类型的功能,但我们有类型的功能Dynamic -> IO ().由于Typeable约束,我们可以toDyn用来转变aDynamic:

mkDyn k f = k (\a -> f (toDyn a))
Run Code Online (Sandbox Code Playgroud)

有更简单的实现(例如,return ()k (\a -> return ()),但这似乎是有道理的.

  • @rampion两个人可以玩这个游戏!`mkDyn =(.(.toDyn))`. (3认同)
  • 我更喜欢尖头版本.如果事情真的只是一个简单的管道,我只使用无点样式.任何(甚至稍微)更复杂,我会在下次阅读代码时后悔. (2认同)

Joe*_*ams 5

我欺骗并使用了Djinn程序.

我首先概括了给出的类型:

f :: (a -> c)
  -> ((a -> b) -> b)
  -> ((c -> b) -> b)
Run Code Online (Sandbox Code Playgroud)

(a -> c)代表的toDyn功能作用,并c代表Dynamic. b代表IO ().

Djinn的结果非常简单:

@djinn (a -> c) -> ((a -> b) -> b) -> ((c -> b) -> b)
f a b c = b (\ d -> c (a d))
Run Code Online (Sandbox Code Playgroud)

使之更具体的(通过更换(a -> c)toDyn功能),我们得到:

mkDyn :: (Typeable a) => ((a -> IO()) -> IO ()) -> ((Dynamic -> IO()) -> IO ())
mkDyn b c = b (\ d -> c (toDyn d))
Run Code Online (Sandbox Code Playgroud)

这与nominolo的答案相符.