【发布时间】:2021-10-15 19:51:17
【问题描述】:
我正试图从 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 中使用它,或者我们是否仅限于使用泛型类型变量(如果我在这里使用了错误的词,请原谅)?
【问题讨论】:
-
fmap必须与您作为参数传递的 any 函数一起使用,但您的定义仅适用于Int -> Int类型的函数。Thing有正确的 kind 作为函子,但这还不够。 -
data Thing a = ...通常意味着a出现在 RHS 上。这就是Functor/fmap所期待的。 -
哇!那很快-谢谢。那么,我有这个权利吗.. 暗示 Functor 的数据类型(在这种情况下是事物)只能使用“通用”类型(这是正确的词),即:我不能具体说明嵌入的数据类型它是“容器”类型(在这种情况下为 Type1 和 Type2)。还是有其他方法可以做到这一点?否则,我们似乎失去了 Haskell 在这种用例中著名的严格类型控制。
-
有一个
mono-traversable包可以让你将data Thing = Type1 Int | Type2 Int Int之类的东西变成类似函子的东西,允许omap foo (Type1 x)和omap foo (Type2 x y),只有在foo没有类型Int -> Int。 -
将
F变成Functor的整个要点 是您可以fmap任何类型a -> b的任何函数,并且生成的函数将将F a带到F b。这意味着在Functor F实例定义中,您只会将映射函数应用于a内部的a值F,而不是任何其他值。如果你想做别的事情,那也不错,也不错,只是和Functor和fmap无关。