我简化了我需要的一些代码的类型签名,它看起来大致如下:
Functor f => f (Maybe a, b) -> (Maybe (f a), f b)
我可以,我该如何实现这样的功能?如果是这样,怎么样?我猜想我需要使用Traversable
来推动仿函数,但是我无法将这一切都放在我脑海中。
答案 0 :(得分:5)
将f
降低一级可以通过以下方式完成:
fn :: Functor f => f (a, b) -> (f a, f b)
fn v = (fmap fst v, fmap snd v)
(请注意,如果您想要两个边,则元组不可遍历。)
第二部分是
Functor f => f (Maybe a) -> Maybe (f a)
此类型仅由const Nothing
居住,因为您可以应用于此值的唯一功能是fmap
,为某些f b
获取b
类型的值。
为了说明为什么第二部分不可能,请考虑IO
是Functor
的实例。如果您可以从您的值中获得Maybe (IO a)
,则对其应用isJust
会泄漏有关原始IO (Maybe a)
值的一些信息而不执行该值。
答案 1 :(得分:4)
我们可以做,如果它是Traversable而不是Functor。
fn :: Traversable t => t (Maybe a, b) -> (Maybe (t a), t b)
fn v = (sequenceA $ fmap fst v, fmap snd v)
可以吗?