double 类型的 Functor 定义被拒绝
double type Functor definition refused
为什么这个函子定义被拒绝?
data Second a b = Ok a b | Ko a b deriving (Show)
instance Functor (Second x) where
fmap f (Ok a b ) = Ok (f a) b
fmap f (Ko a b ) = Ko a (f b)
GHCi, version 8.0.1
main.hs:4:22: error:
• Couldn't match type ‘b’ with ‘x’
‘b’ is a rigid type variable bound by
the type signature for:
fmap :: forall a b. (a -> b) -> Second x a -> Second x b
at main.hs:4:3
‘x’ is a rigid type variable bound by
the instance declaration at main.hs:3:10
Expected type: Second x b
Actual type: Second b a
• In the expression: Ok (f a) b
In an equation for ‘fmap’: fmap f (Ok a b) = Ok (f a) b
In the instance declaration for ‘Functor (Second x)’
• Relevant bindings include
a :: x (bound at main.hs:4:14)
f :: a -> b (bound at main.hs:4:8)
fmap :: (a -> b) -> Second x a -> Second x b (bound at main.hs:4:3)
main.hs:4:28: error:
• Couldn't match expected type ‘a’ with actual type ‘x’
‘x’ is a rigid type variable bound by
the instance declaration at main.hs:3:10
‘a’ is a rigid type variable bound by
the type signature for:
fmap :: forall a b. (a -> b) -> Second x a -> Second x b
at main.hs:4:3
• In the first argument of ‘f’, namely ‘a’
In the first argument of ‘Ok’, namely ‘(f a)’
In the expression: Ok (f a) b
• Relevant bindings include
b :: a (bound at main.hs:4:16)
a :: x (bound at main.hs:4:14)
f :: a -> b (bound at main.hs:4:8)
fmap :: (a -> b) -> Second x a -> Second x b (bound at main.hs:4:3)
这一切是什么意思?请帮忙。
如果你打开 Functor
的定义,你会看到 Second
的第一个参数保持不变,而它的第二个参数正在等待转换。
class Functor f where
fmap :: (s -> t) -> f s -> f t
(我已将类型变量 a
和 b
分别重命名为 s
和 t
,因为您还有值变量 a
和 b
.)
那个 class
给了我们,在你的特定 instance
instance Functor (Second x) where
-- fmap :: (s -> t) -> (Second x) s -> (Second x) t
-- i.e. (s -> t) -> Second x s -> Second x t
现在,当您实施 fmap
时,您必须确保 fmap
的 用户 可以选择任何 x
,s
和 t
他们想要的。所以你不能对它们做任何假设:它们代表任意的、可能不同的类型。这就是错误消息在谈论 "rigid" 类型变量时的意思:您的 代码不允许为它们选择特定类型,因此它的用户可以。编译器抱怨说你承诺了一个 非常多态的 函数,但提供了一个较少多态的函数,它只在 x=s=t
.
时进行类型检查
也就是你写的时候
fmap f (Ok a b) = Ok (f a) b
你有
f :: s -> t
Ok a b :: Second x s
a :: x
b :: s
你回来了
Ok (f a) b :: Second x t
需要
f a :: x -- clearly not true, as f :: s -> t
b :: t -- clearly not true, as b :: s
f a
需要
a :: s -- clearly not true, as a :: x
所以,是的,有很多错误。
A Functor
实例允许您在对应于类型的 last 参数的位置转换数据,即 b
in
data Second a b = Ok a b | Ko a b deriving (Show)
所以你的
fmap f (Ko a b ) = Ko a (f b)
很好,但是你的
fmap f (Ok a b ) = Ok (f a) b
命中不同参数的用法,但不正常。
fmap f (Ok a b ) = Ok a (f b)
会起作用。将 data
声明更改为
data Second a b = Ok b a | Ko a b deriving (Show)
并让你的 instance
保持原样。
任一修复都有效,但不要同时执行这两个 "just to be on the safe side"!
为什么这个函子定义被拒绝?
data Second a b = Ok a b | Ko a b deriving (Show)
instance Functor (Second x) where
fmap f (Ok a b ) = Ok (f a) b
fmap f (Ko a b ) = Ko a (f b)
GHCi, version 8.0.1
main.hs:4:22: error:
• Couldn't match type ‘b’ with ‘x’
‘b’ is a rigid type variable bound by
the type signature for:
fmap :: forall a b. (a -> b) -> Second x a -> Second x b
at main.hs:4:3
‘x’ is a rigid type variable bound by
the instance declaration at main.hs:3:10
Expected type: Second x b
Actual type: Second b a
• In the expression: Ok (f a) b
In an equation for ‘fmap’: fmap f (Ok a b) = Ok (f a) b
In the instance declaration for ‘Functor (Second x)’
• Relevant bindings include
a :: x (bound at main.hs:4:14)
f :: a -> b (bound at main.hs:4:8)
fmap :: (a -> b) -> Second x a -> Second x b (bound at main.hs:4:3)
main.hs:4:28: error:
• Couldn't match expected type ‘a’ with actual type ‘x’
‘x’ is a rigid type variable bound by
the instance declaration at main.hs:3:10
‘a’ is a rigid type variable bound by
the type signature for:
fmap :: forall a b. (a -> b) -> Second x a -> Second x b
at main.hs:4:3
• In the first argument of ‘f’, namely ‘a’
In the first argument of ‘Ok’, namely ‘(f a)’
In the expression: Ok (f a) b
• Relevant bindings include
b :: a (bound at main.hs:4:16)
a :: x (bound at main.hs:4:14)
f :: a -> b (bound at main.hs:4:8)
fmap :: (a -> b) -> Second x a -> Second x b (bound at main.hs:4:3)
这一切是什么意思?请帮忙。
如果你打开 Functor
的定义,你会看到 Second
的第一个参数保持不变,而它的第二个参数正在等待转换。
class Functor f where
fmap :: (s -> t) -> f s -> f t
(我已将类型变量 a
和 b
分别重命名为 s
和 t
,因为您还有值变量 a
和 b
.)
那个 class
给了我们,在你的特定 instance
instance Functor (Second x) where
-- fmap :: (s -> t) -> (Second x) s -> (Second x) t
-- i.e. (s -> t) -> Second x s -> Second x t
现在,当您实施 fmap
时,您必须确保 fmap
的 用户 可以选择任何 x
,s
和 t
他们想要的。所以你不能对它们做任何假设:它们代表任意的、可能不同的类型。这就是错误消息在谈论 "rigid" 类型变量时的意思:您的 代码不允许为它们选择特定类型,因此它的用户可以。编译器抱怨说你承诺了一个 非常多态的 函数,但提供了一个较少多态的函数,它只在 x=s=t
.
也就是你写的时候
fmap f (Ok a b) = Ok (f a) b
你有
f :: s -> t
Ok a b :: Second x s
a :: x
b :: s
你回来了
Ok (f a) b :: Second x t
需要
f a :: x -- clearly not true, as f :: s -> t
b :: t -- clearly not true, as b :: s
f a
需要
a :: s -- clearly not true, as a :: x
所以,是的,有很多错误。
A Functor
实例允许您在对应于类型的 last 参数的位置转换数据,即 b
in
data Second a b = Ok a b | Ko a b deriving (Show)
所以你的
fmap f (Ko a b ) = Ko a (f b)
很好,但是你的
fmap f (Ok a b ) = Ok (f a) b
命中不同参数的用法,但不正常。
fmap f (Ok a b ) = Ok a (f b)
会起作用。将 data
声明更改为
data Second a b = Ok b a | Ko a b deriving (Show)
并让你的 instance
保持原样。
任一修复都有效,但不要同时执行这两个 "just to be on the safe side"!