如何在使用具体类型的数据类型上编写 Functor?
How do you write a Functor on a data type that uses concrete types?
我正试图从 GO 的世界进入 Haskell,所以几乎可以肯定我遗漏了一些微不足道的东西,但这让我很困惑!
以下编译但没有任何用处。
data Thing a = Type1 Int | Type2 Int Int deriving Show
instance Functor Thing where
fmap func (Type1 a) = Type1 a
fmap func (Type2 a b) = Type2 a b
一旦我尝试实际使用“func”,它就无法编译。例如,像这样在两个模式规则的第一个中使用“func”..
data Thing a = Type1 Int | Type2 Int Int deriving Show
instance Functor Thing where
fmap func (Type1 a) = Type1 (func a)
fmap func (Type2 a b) = Type2 a b
出现以下错误,但如果我使用“Type1 a | Type2 a a”声明“Thing”,则编译正常。
x2.hs:4:34:
Couldn't match expected type ‘Int’ with actual type ‘b’
‘b’ is a rigid type variable bound by
the type signature for fmap :: (a -> b) -> Thing a -> Thing b
at x2.hs:4:5
Relevant bindings include
func :: a -> b (bound at x2.hs:4:10)
fmap :: (a -> b) -> Thing a -> Thing b (bound at x2.hs:4:5)
In the first argument of ‘Type1’, namely ‘(func a)’
In the expression: Type1 (func a)
x2.hs:4:39:
Couldn't match expected type ‘a’ with actual type ‘Int’
‘a’ is a rigid type variable bound by
the type signature for fmap :: (a -> b) -> Thing a -> Thing b
at x2.hs:4:5
Relevant bindings include
func :: a -> b (bound at x2.hs:4:10)
fmap :: (a -> b) -> Thing a -> Thing b (bound at x2.hs:4:5)
In the first argument of ‘func’, namely ‘a’
In the first argument of ‘Type1’, namely ‘(func a)’
任何人都可以解释为什么以及我可以做些什么来解决它吗?是否可以在数据定义中使用具体类型,然后在 Functor 中使用它,或者我们是否仅限于使用泛型类型变量(如果我在这里使用了错误的词,请原谅)?
Is it possible to use concrete types in a data definition and then use that in a Functor or are we limited to using generic type variables (excuse me if I'm using the wrong words here)?
你不受限制。但是,只有类型为(或提及)数据声明中最后一个通用变量的字段才能在您的 Functor
实例中进行修改。 (类型检查器允许对具有其他类型的字段进行一些修改;但所有这些都会导致违反仿函数法则。)因此,例如,它混合了通用字段和具体字段:
data Thing a = Type1 Int a | Type2 Int Int
instance Functor Thing where
fmap f (Type1 n a) = Type1 n (f a)
fmap f (Type2 m n) = Type2 m n
当然,没有什么能阻止您编写另一个函数,它没有命名 fmap
,它可以随心所欲。所以,这也可以:
data Thing = Type1 Int | Type2 Int Int
notFmap :: (Int -> Int) -> Thing -> Thing
notFmap f (Type1 n) = Type1 (f n)
notFmap f (Type2 m n) = Type2 m n
我正试图从 GO 的世界进入 Haskell,所以几乎可以肯定我遗漏了一些微不足道的东西,但这让我很困惑!
以下编译但没有任何用处。
data Thing a = Type1 Int | Type2 Int Int deriving Show
instance Functor Thing where
fmap func (Type1 a) = Type1 a
fmap func (Type2 a b) = Type2 a b
一旦我尝试实际使用“func”,它就无法编译。例如,像这样在两个模式规则的第一个中使用“func”..
data Thing a = Type1 Int | Type2 Int Int deriving Show
instance Functor Thing where
fmap func (Type1 a) = Type1 (func a)
fmap func (Type2 a b) = Type2 a b
出现以下错误,但如果我使用“Type1 a | Type2 a a”声明“Thing”,则编译正常。
x2.hs:4:34:
Couldn't match expected type ‘Int’ with actual type ‘b’
‘b’ is a rigid type variable bound by
the type signature for fmap :: (a -> b) -> Thing a -> Thing b
at x2.hs:4:5
Relevant bindings include
func :: a -> b (bound at x2.hs:4:10)
fmap :: (a -> b) -> Thing a -> Thing b (bound at x2.hs:4:5)
In the first argument of ‘Type1’, namely ‘(func a)’
In the expression: Type1 (func a)
x2.hs:4:39:
Couldn't match expected type ‘a’ with actual type ‘Int’
‘a’ is a rigid type variable bound by
the type signature for fmap :: (a -> b) -> Thing a -> Thing b
at x2.hs:4:5
Relevant bindings include
func :: a -> b (bound at x2.hs:4:10)
fmap :: (a -> b) -> Thing a -> Thing b (bound at x2.hs:4:5)
In the first argument of ‘func’, namely ‘a’
In the first argument of ‘Type1’, namely ‘(func a)’
任何人都可以解释为什么以及我可以做些什么来解决它吗?是否可以在数据定义中使用具体类型,然后在 Functor 中使用它,或者我们是否仅限于使用泛型类型变量(如果我在这里使用了错误的词,请原谅)?
Is it possible to use concrete types in a data definition and then use that in a Functor or are we limited to using generic type variables (excuse me if I'm using the wrong words here)?
你不受限制。但是,只有类型为(或提及)数据声明中最后一个通用变量的字段才能在您的 Functor
实例中进行修改。 (类型检查器允许对具有其他类型的字段进行一些修改;但所有这些都会导致违反仿函数法则。)因此,例如,它混合了通用字段和具体字段:
data Thing a = Type1 Int a | Type2 Int Int
instance Functor Thing where
fmap f (Type1 n a) = Type1 n (f a)
fmap f (Type2 m n) = Type2 m n
当然,没有什么能阻止您编写另一个函数,它没有命名 fmap
,它可以随心所欲。所以,这也可以:
data Thing = Type1 Int | Type2 Int Int
notFmap :: (Int -> Int) -> Thing -> Thing
notFmap f (Type1 n) = Type1 (f n)
notFmap f (Type2 m n) = Type2 m n