Haskell fmap over custom data type

时间:2018-05-23 14:53:08

标签: haskell polymorphism functor

在我的项目中,我有一些看起来像这样的数据类型

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

然而,我遇到了错误的错误。

问题是如何声明一个可以多态应用于这些数据结构的函数?

2 个答案:

答案 0 :(得分:6)

您只能在参数化类型Functor上)精确地声明* -> *实例:一种仍需要额外(且恰好一个)类型参数的类型

首先,我们需要引入一个类型参数。即使你从未计划使用除Int以外的其他内容,我们也可以轻松地将其抽象出来:

data Structure a = Structure [a] Bool Int

我们可以举例说明StructureA类型的同义词

type StructureA = Structure Int

现在我们可以通过编写:

使其成为Functor个实例
instance Functor Structure where
    fmap f (Structure as b c) = ...

请注意,我们这里(Structure a),但是Structure,因为 - 就像我们已经说过的那样 - fmap可以自由更改类型集合的工作原理:f函数可以使用Int -> Char类型将Structure Int转换为Structure Char

现在我们仍然需要实施fmapfmap的类型为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) = Structure (fmap f as) b c

答案 1 :(得分:2)

如果类型构造函数只有一个参数,那么它只能是一个函子。类型构造函数StructureA根本没有类型参数,因此不能成为仿函数。