我有这个蹩脚的尝试:
fmap2 :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
fmap2 f f2 = (fmap2 f . fmap f2)
它应该像这样工作:
fmap2 negate [[1,2], [3]] -- Returns [[-1,-2],[-3]]
fmap2 head [Just "abc",Nothing,Just "def"] -- Returns [Just 'a',Nothing,Just 'e']
请注意,这是一个练习。 (我尝试了大约1.5个小时,但没有找到任何解决方案。)
问:我做错了什么?
当你陷入这样的困境时。我建议使用类型孔,因为它们会带您朝正确的方向前进
fmap2 :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
fmap2 f nested_functor = fmap _something nested_functor
-- | | |- notice this underscore
-- | |- clearly we need fo fmap something over the nested_functor but we don't know what yet
-- |- Use better names usually help. Haskellers tend to use ver short names, but that's not appropiate always
如果您尝试编译此代码,
ghc
会注意到_something
,并会建议您使用它的类型
Found hole: _something :: g a -> g b <-- This is interesting
Where: ‘a’, ‘g’, ‘b’ ... (blah blah blah, not interesting)
Or perhaps ‘_something’ is mis-spelled, or not in scope
我们知道,给定
_something
,g a -> g b
需要具有类型 Functor g
。因此:
fmap2 :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
fmap2 f nested_functor = fmap something nested_functor
where
-- remember something :: Functor g => g a -> g b
something = undefined -- left as an exercise
您应该
fmap
使用函子映射作为内部结构的函数,所以类似于:
fmap2 :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
fmap2 f = fmap (fmap …)
我留下填写
…
部分作为练习。