关于Haskell的精彩之处。函数的类型几乎决定了它的实现。对于这个就是这种情况,但是......我的大脑并没有在这里包围嵌套函数:
mkDyn :: (Typeable a) => ((a -> IO()) -> IO ()) -> ((Dynamic -> IO()) -> IO ())
唯一的问题是如何处理将要求的fromDynamic调用中的错误处理,但是......一旦我完成其余的考虑,我就可以处理它。我猜想在某个地方需要有类似的东西。但我似乎无法得到包装器lambda的东西。
case fromDynamic x of
Just x -> f x
Nothing -> undefined -- TODO
答案 0 :(得分:10)
我认为您需要toDyn
,而不是fromDynamic
。所以让我们慢慢来这样做:
mkDyn :: Typeable a =>
((a -> IO ()) -> IO ())
-> (Dynamic -> IO ())
-> IO ()
mkDyn k f = ...
我们的返回类型应为IO ()
,我们可以通过致电k
或f
来获取此类型。调用f
对我们没什么帮助,因为我们会以某种方式实现Dynamic
,但我们不能(明智地)从k
那样做。所以我们想打电话给k
。 k
需要另一个函数作为参数,所以让我们这样开始:
mkDyn k f = k (\a -> ...)
所以函数的参数是Typeable a => a -> IO ()
。我们没有该类型的函数,但我们有Dynamic -> IO ()
类型的函数。由于Typeable
约束,我们可以使用toDyn
将a
转换为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
代表Dynamic
。 b
代表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))