Haskell fmap 自定义数据类型
Haskell fmap over custom data type
在我的项目中,我有一些数据类型如下所示
data StructureA = StructureA [Int] Bool Int
data StructureB = StructureB [String] String
我的目标是将函数映射到此类数据类型实例中包含的数组
inst = StructureA [1,1,1] True 0
fmap (+1) inst -- [2,2,2]
我最初的解决方案是这样的
instance Functor StructureA where
fmap (StructureA arr _ _) = fmap arr
但是,我收到类型不匹配错误。
问题是我如何声明一个可以多态应用于此类数据结构的函数?
您只能在 参数化类型 (准确地说是 * -> *
)上声明一个 Functor
实例:一个仍然需要额外(和恰好一个)类型参数。
所以首先我们需要引入一个类型参数。即使你从不打算使用 Int
s 之外的东西,我们也可以很容易地将它抽象出来:
data Structure <b>a</b> = Structure [<b>a</b>] Bool Int
例如,我们可以将 StructureA
声明为 类型同义词 :
type StructureA = Structure Int
现在我们可以使它成为一个 Functor
实例,写成:
instance Functor <b>Structure</b> where
fmap f (Structure as b c) = ...
请注意,我们这里 不是 写 (Structure a)
,而是写 Structure
,因为 - 正如我们已经说过的 - fmap
有自由更改集合工作的类型:f
函数可以有例如类型 Int -> Char
将 Structure Int
转换为 Structure Char
.
现在还需要实施fmap
。 fmap
的类型为 fmap :: Functor f => (a -> b) -> f a -> f b
,这意味着它接受一个函数,在本例中为 Structure a
,并构造一个 Structure b
。根据您的问题(以及我们做出的设计决策),我们唯一可以映射的部分是第一个参数,因此我们构造一个新的 Structure
,其中第二个参数是 fmap f
的结果,然后在第二个参数上,所以:
instance Functor Structure where
fmap f (Structure as b c) = <b>Structure (fmap f as) b c</b>
只有只有一个参数的类型构造函数才能成为函子。类型构造函数 StructureA
根本没有类型参数,因此不能是函子。
在我的项目中,我有一些数据类型如下所示
data StructureA = StructureA [Int] Bool Int
data StructureB = StructureB [String] String
我的目标是将函数映射到此类数据类型实例中包含的数组
inst = StructureA [1,1,1] True 0
fmap (+1) inst -- [2,2,2]
我最初的解决方案是这样的
instance Functor StructureA where
fmap (StructureA arr _ _) = fmap arr
但是,我收到类型不匹配错误。
问题是我如何声明一个可以多态应用于此类数据结构的函数?
您只能在 参数化类型 (准确地说是 * -> *
)上声明一个 Functor
实例:一个仍然需要额外(和恰好一个)类型参数。
所以首先我们需要引入一个类型参数。即使你从不打算使用 Int
s 之外的东西,我们也可以很容易地将它抽象出来:
data Structure <b>a</b> = Structure [<b>a</b>] Bool Int
例如,我们可以将 StructureA
声明为 类型同义词 :
type StructureA = Structure Int
现在我们可以使它成为一个 Functor
实例,写成:
instance Functor <b>Structure</b> where
fmap f (Structure as b c) = ...
请注意,我们这里 不是 写 (Structure a)
,而是写 Structure
,因为 - 正如我们已经说过的 - fmap
有自由更改集合工作的类型:f
函数可以有例如类型 Int -> Char
将 Structure Int
转换为 Structure Char
.
现在还需要实施fmap
。 fmap
的类型为 fmap :: Functor f => (a -> b) -> f a -> f b
,这意味着它接受一个函数,在本例中为 Structure a
,并构造一个 Structure b
。根据您的问题(以及我们做出的设计决策),我们唯一可以映射的部分是第一个参数,因此我们构造一个新的 Structure
,其中第二个参数是 fmap f
的结果,然后在第二个参数上,所以:
instance Functor Structure where
fmap f (Structure as b c) = <b>Structure (fmap f as) b c</b>
只有只有一个参数的类型构造函数才能成为函子。类型构造函数 StructureA
根本没有类型参数,因此不能是函子。