如何在Haskell中实现此功能

时间:2011-09-10 17:35:28

标签: haskell

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

mkDyn :: (Typeable a) => ((a -> IO()) -> IO ()) -> ((Dynamic -> IO()) -> IO ())

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

case fromDynamic x of
  Just x -> f x
  Nothing -> undefined -- TODO 

2 个答案:

答案 0 :(得分:10)

我认为您需要toDyn,而不是fromDynamic。所以让我们慢慢来这样做:

mkDyn :: Typeable a =>
         ((a -> IO ()) -> IO ())
      -> (Dynamic -> IO ())
      -> IO ()
mkDyn k f = ...

我们的返回类型应为IO (),我们可以通过致电kf来获取此类型。调用f对我们没什么帮助,因为我们会以某种方式实现Dynamic,但我们不能(明智地)从k那样做。所以我们想打电话给kk需要另一个函数作为参数,所以让我们这样开始:

mkDyn k f = k (\a -> ...)

所以函数的参数是Typeable a => a -> IO ()。我们没有该类型的函数,但我们有Dynamic -> IO ()类型的函数。由于Typeable约束,我们可以使用toDyna转换为Dynamic并获取:

mkDyn k f = k (\a -> f (toDyn a))

有更简单的实现(例如,return ()k (\a -> return ()),但这个实现似乎有意义。

答案 1 :(得分:5)

我作弊并使用Djinn program

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

f :: (a -> c)
  -> ((a -> b) -> b)
  -> ((c -> b) -> b)

(a -> c)代表toDyn function函数,c代表Dynamicb代表IO ()

Djinn的结果非常简单:

@djinn (a -> c) -> ((a -> b) -> b) -> ((c -> b) -> b)
f a b c = b (\ d -> c (a d))

使其更具体(通过将(a -> c)替换为toDyn函数),我们得到:

mkDyn :: (Typeable a) => ((a -> IO()) -> IO ()) -> ((Dynamic -> IO()) -> IO ())
mkDyn b c = b (\ d -> c (toDyn d))

匹配nominolo's answer