gpt4 book ai didi

haskell - 双类型仿函数定义被拒绝

转载 作者:行者123 更新时间:2023-12-02 11:11:35 25 4
gpt4 key购买 nike

为什么这个仿函数定义被拒绝?

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)

get a lot of errors :
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

(我已将类型变量 ab 分别重命名为 st ,因为您还有值变量 ab 。)

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 , st他们要。所以你不能对它们做任何假设:它们代表任意的,可能是不同的类型。这就是错误消息在谈论“刚性”类型变量时的含义:您的代码不允许为它们选择特定类型,以便其用户可以选择。编译器提示您 promise 提供一个非常多态的函数,但提供了一个较少多态的函数,该函数仅在 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

所以,是的,很多错误。

一个 Functor instance 允许您在与类型的最后一个参数对应的位置转换数据,即 b
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照原样。

任何一种修复都有效,但不要同时“为了安全起见”!

关于haskell - 双类型仿函数定义被拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47477052/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com