Mau*_*ira -2 haskell types compiler-errors functor
为什么这个算符定义被拒绝了?
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)
Run Code Online (Sandbox Code Playgroud)
我收到很多错误:
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)
Run Code Online (Sandbox Code Playgroud)
这是什么意思呢?请帮忙.
如果解压缩你的定义,Functor你会看到Second第一个参数保持不变,而第二个参数是转换参数.
class Functor f where
fmap :: (s -> t) -> f s -> f t
Run Code Online (Sandbox Code Playgroud)
(在那里我已经改名类型变量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
Run Code Online (Sandbox Code Playgroud)
现在,当你实现fmap,你必须确保该用户的fmap可以任意选择x,s和t他们想要的.所以你不必对它们做任何假设:它们代表任意的,可能是不同的类型.这就是错误消息在谈论"严格"类型变量时的意思:您的代码不允许为它们选择特定类型,以便其用户可以.编译器抱怨你承诺一个非常多态的函数,但是提供一个不那么多态的函数,只有在什么时候才会出现x=s=t.
也就是说,当你写作
fmap f (Ok a b) = Ok (f a) b
Run Code Online (Sandbox Code Playgroud)
你有
f :: s -> t
Ok a b :: Second x s
a :: x
b :: s
Run Code Online (Sandbox Code Playgroud)
你回来了
Ok (f a) b :: Second x t
Run Code Online (Sandbox Code Playgroud)
这需要
f a :: x -- clearly not true, as f :: s -> t
b :: t -- clearly not true, as b :: s
Run Code Online (Sandbox Code Playgroud)
这里f a需要
a :: s -- clearly not true, as a :: x
Run Code Online (Sandbox Code Playgroud)
所以,是的,很多错误.
一个Functor实例让你在与该类型相应的位置变换数据最后的参数,即b在
data Second a b = Ok a b | Ko a b deriving (Show)
Run Code Online (Sandbox Code Playgroud)
所以你的
fmap f (Ko a b ) = Ko a (f b)
Run Code Online (Sandbox Code Playgroud)
很好,但你的
fmap f (Ok a b ) = Ok (f a) b
Run Code Online (Sandbox Code Playgroud)
点击使用不同的参数,但不行.
fmap f (Ok a b ) = Ok a (f b)
Run Code Online (Sandbox Code Playgroud)
会工作.正如将data声明改为
data Second a b = Ok b a | Ko a b deriving (Show)
Run Code Online (Sandbox Code Playgroud)
然后离开你的instance原样.
要么修复工作,但不要两者兼顾"只是为了安全起见"!