为数据类型定义 fmap
Defining fmap for data type
所以我有那些数据类型:
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 函数感到迷茫..
fmap
有签名:
fmap :: Functor f => (a -> b) -> f a -> f b
所以这意味着它将 - 给定一个从 a
映射到 b
的函数,生成一个映射 Stuff a
到 Stuff b
的函数。但是Stuff
的属性不是a
,所以你不能直接在参数上调用f
.
所以这可能意味着您要先 使 StuffPart a
成为 Functor
。例如:
instance Functor StuffPart where
<b>fmap</b> f (Add x y) = Add (f x) (<b>fmap</b> f y)
<b>fmap</b> _ End = End
看起来 StuffPart
是您自定义的列表 ([]
)。
然后我们可以简单地定义:
instance Functor Stuff where
fmap f (Stuff x y) = Stuff (<b>fmap</b> f x) (<b>fmap</b> f y)
请注意,我们在这里调用的 fmap
s(粗体部分)指的是我们在上面定义的函数(在 Functor StuffPart
的上下文中)。
编辑:您没有使StuffPart
成为Functor
本身。如果你真的不想那样,你可以简单地定义一个函数 foo :: (a -> b) -> StuffPart a -> StuffPart b
并调用该函数,但这对我来说实际上看起来像糟糕的代码设计,因为如果你稍后改变 StuffPart
的定义那么部分大约 Stuff
也必须改变,使其变得更难。但如果你真的想要那个,你可以使用:
instance Functor Stuff where
fmap f (Stuff x y) = Stuff (<b>foo</b> x) (<b>foo</b> y)
where <b>foo</b> (Add x y) = Add (f x) (<b>foo</b> y)
<b>foo</b> End = End
您还需要一个 Functor
实例用于 StuffPart
:
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
所以我有那些数据类型:
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 函数感到迷茫..
fmap
有签名:
fmap :: Functor f => (a -> b) -> f a -> f b
所以这意味着它将 - 给定一个从 a
映射到 b
的函数,生成一个映射 Stuff a
到 Stuff b
的函数。但是Stuff
的属性不是a
,所以你不能直接在参数上调用f
.
所以这可能意味着您要先 使 StuffPart a
成为 Functor
。例如:
instance Functor StuffPart where
<b>fmap</b> f (Add x y) = Add (f x) (<b>fmap</b> f y)
<b>fmap</b> _ End = End
看起来 StuffPart
是您自定义的列表 ([]
)。
然后我们可以简单地定义:
instance Functor Stuff where
fmap f (Stuff x y) = Stuff (<b>fmap</b> f x) (<b>fmap</b> f y)
请注意,我们在这里调用的 fmap
s(粗体部分)指的是我们在上面定义的函数(在 Functor StuffPart
的上下文中)。
编辑:您没有使StuffPart
成为Functor
本身。如果你真的不想那样,你可以简单地定义一个函数 foo :: (a -> b) -> StuffPart a -> StuffPart b
并调用该函数,但这对我来说实际上看起来像糟糕的代码设计,因为如果你稍后改变 StuffPart
的定义那么部分大约 Stuff
也必须改变,使其变得更难。但如果你真的想要那个,你可以使用:
instance Functor Stuff where
fmap f (Stuff x y) = Stuff (<b>foo</b> x) (<b>foo</b> y)
where <b>foo</b> (Add x y) = Add (f x) (<b>foo</b> y)
<b>foo</b> End = End
您还需要一个 Functor
实例用于 StuffPart
:
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