【问题标题】:Defining fmap for data type为数据类型定义 fmap
【发布时间】:2017-06-18 22:57:19
【问题描述】:

所以我有这些数据类型:

data Stuff a = Stuff (StuffPart a) (StuffPart a) deriving (Show,Eq)
data StuffPart a = Add a (StuffPart a)| End deriving (Show,Eq)

,现在可以为 Stuff 编写 fmap 函数吗?类似的东西:

instance Functor Stuff
  where 
   fmap f (Stuff x y) = Stuff (f x) (f y)

显然我的 fmap 无法正常工作,但我可以做些什么来使其正常工作。 我也尝试过类似的代码:

instance Functor Stuff
  where 
   fmap f (Stuff x y) = Stuff (f x) (fmap f y)

不知何故,我对 fmap 函数感到迷茫..

【问题讨论】:

  • 你需要一个StuffPart,就像一个列表一样......或者只是启用DeriveFunctor来为你做这项工作......

标签: haskell functor


【解决方案1】:

fmap 有签名:

fmap :: Functor f => (a -> b) -> f a -> f b

这意味着它将 - 给定一个从a 映射到b 的函数,生成一个将Stuff a 映射到Stuff b 的函数。但是Stuff 的属性不是as,所以你不能在参数上直接调用f

所以这可能意味着您想先StuffPart a 设为Functor。例如:

instance Functor StuffPart where
    fmap f (Add x y) = Add (f x) (fmap f y)
    fmap _ End = End

看起来StuffPart 是您对列表的自定义定义 ([])。

然后我们可以简单地定义:

instance Functor Stuff where
    fmap f (Stuff x y) = Stuff (fmap f x) (fmap f y)

注意我们这里调用的fmaps(黑体字)指的是我们上面定义的函数(在Functor StuffPart的上下文中)。

编辑:你没有StuffPart 变成Functor 本身。如果你真的不想这样,你可以简单地定义一个函数 foo :: (a -> b) -> StuffPart a -> StuffPart b 并调用该函数,但这对我来说实际上看起来像是糟糕的代码设计,因为如果你稍后更改 StuffPart 的定义,那么部分关于 Stuff也必须改变,让它变得更难。但如果你真的想要,你可以使用:

instance Functor Stuff where
    fmap f (Stuff x y) = Stuff (foo x) (foo y)
        where foo (Add x y) = Add (f x) (foo y)
              foo End = End

【讨论】:

  • 谢谢!!哦,我明白了,但是如果不让 Stuffpart 成为 Functor 就没有其他选择吗?
  • @itonva:是的,您可以定义一个函数foo :: (a -> b) -> StuffPart a -> StuffPart b,然后调用该函数。但在这里,将StuffPart 也设为函数似乎是合理的。
  • 好的,我明白了。感谢您的帮助,我真的很感激 :)
  • @Wilem Van Onsem:是的,实际上最好将StuffPart 设为Functor,我只是想知道是否还有其他可能性。
  • @itonva 如果你不想深入研究这些事情(虽然我个人认为手动实现这样的Functor 实例很好)你可以添加{-# LANGUAGE DeriveFunctor #-} pragma,它允许你添加Functorderiving 子句中。
【解决方案2】:

您还需要FunctorStuffPart 实例:

instance Functor Stuff where
  fmap f (Stuff p1 p2) = Stuff (fmap f p1) (fmap f p2)

instance Functor StuffPart where
  fmap f (Add x sp) = Add (f x) (fmap f sp)
  fmap f End = End

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    相关资源
    最近更新 更多