gpt4 book ai didi

haskell - 为什么我不能在 Haskell 中使用 id 制作 Functor 的 Either 实例?

转载 作者:行者123 更新时间:2023-12-04 13:26:39 25 4
gpt4 key购买 nike

定制时 Either , 和 Functor ,只是为了理解更清晰的类型和类型类,我发现了以下情况:

Functor

module Functor (Functor, fmap) where

import Prelude hiding(Functor, fmap)

class Functor f where
fmap :: (a -> b) -> f a -> f b

Either
module Either(Either(..)) where
import Prelude hiding(Either(..), Functor, fmap)

data Either a b = Left a | Right b deriving(Show)

instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap _ (Left x) = Left x

上面显示的代码可以正常编译,但是如果我将其更改为使用 id ,它不编译:
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap _ = id

为什么??我错过了什么?以下代码也不起作用:
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f all@(Left x) = all

...这在我看来很奇怪,因为下面显示的代码编译:
data Shape = Circle Point Float | Rectangle Point Point deriving (Show)

data Point = Point Float Float deriving (Show)

test :: Shape -> String
test (Circle _ x) = show x
test all@(Rectangle _ x) = show all ++ " - "++ show x

先感谢您

最佳答案

你想要做的归结为:

f :: Either a Bool -> Either a ()
f (Right _) = Right ()
f left = left

有错误:
foo.hs:3:7:
Couldn't match type ‘Bool’ with ‘()’
Expected type: Either a ()
Actual type: Either a Bool
In the expression: left
In an equation for ‘f’: f left = left
Failed, modules loaded: none.
left绑定(bind)到函数参数。所以类型检查器知道它的类型是 Either a Bool .然后它被用作返回值。我们从类型 f :: Either a Bool -> Either a () 中得知返回值必须是 Either a () 类型.如果 left是一个有效的返回值,它的类型必须匹配 f 的返回类型.所以 Either a ()必须等于 Either a Bool ;它不是,所以类型检查器拒绝该程序。

反过来,它与此基本上是相同的问题:
λ let l = Left () :: Either () ()
l :: Either () ()

λ l
Left ()
it :: Either () ()

λ l :: Either () Bool

<interactive>:10:1:
Couldn't match type ‘()’ with ‘Bool’
Expected type: Either () Bool
Actual type: Either () ()
In the expression: l :: Either () Bool
In an equation for ‘it’: it = l :: Either () Bool

我们给了 l绑定(bind)和类型,然后尝试将其用作不同的类型。这是无效的(通过 id 提供它也不会改变它的类型)。即使 Left ()也是 Either () Bool 类型值的有效源代码文本,这并不意味着已知类型为 Either () () 的特定值可以用源文本 Left () 定义可以像 Either () Bool 类型一样使用.

如果你有一个多态值,你可以这样做:
λ let l = Left ()
l :: Either () b

λ l :: Either () ()
Left ()
it :: Either () ()

λ l :: Either () Bool
Left ()
it :: Either () Bool

注意原来的 l这里的值在 b 中是多态的;它可以用作 Either () b对于任何 b。

但是你的 fmap情况略有不同。 功能 fmapb 中是多态的,但其参数的值是“在多态范围内”;在这一点上,您的论点类型为 b已被 fmap 的调用者选择为某种特定类型,因此它是“可以通过任何方式实现的某种未知类型”,而不是“我想选择的任何类型”。无法以某种方式转换 Either a b 类型的值转换为 Either a c 类型的值,所以你必须提取 a值,然后创建一个 Either a c包含它。

关于haskell - 为什么我不能在 Haskell 中使用 id 制作 Functor 的 Either 实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31552800/

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