多层次函子

问题描述 投票:0回答:2

我有这个蹩脚的尝试:

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个小时,但没有找到任何解决方案。)

问:我做错了什么?

list function haskell functional-programming functor
2个回答
2
投票

当你陷入这样的困境时。我建议使用类型孔,因为它们会带您朝正确的方向前进

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

0
投票

您应该

fmap
使用函子映射作为内部结构的函数,所以类似于:

fmap2 :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b)
fmap2 f = fmap (fmap …)

我留下填写

部分作为练习。

© www.soinside.com 2019 - 2024. All rights reserved.