在我的项目中,我有一些看起来像这样的数据类型
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
然而,我遇到了错误的错误。
问题是如何声明一个可以多态应用于这些数据结构的函数?
答案 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
。
现在我们仍然需要实施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) = Structure (fmap f as) b c
答案 1 :(得分:2)
如果类型构造函数只有一个参数,那么它只能是一个函子。类型构造函数StructureA
根本没有类型参数,因此不能成为仿函数。