gpt4 book ai didi

syntax - 'err@(Left _)'和 'Left err'有什么区别

转载 作者:行者123 更新时间:2023-12-01 07:43:46 25 4
gpt4 key购买 nike

我正在尝试 中的代码。

在 GHC 版本 6.10.4 上:

data ParseState = ParseState {
string :: String
} deriving (Show)

newtype Parse a = Parse {
runParse :: ParseState -> Either String (a, ParseState)
}

parse :: Parse a -> String -> Either String a
parse parser initState =
case runParse parser (ParseState initState) of
Left err -> Left err
Right (result, _) -> Right result

在我将 'Left err' 更改为 'err@(Left _)' 之前一切都很好:

--  err@(Left _)      -> err
{-
- Occurs check: cannot construct the infinite type:
- a = (a, ParseState)
- When generalising the type(s) for `parse'
-}

有什么想法吗?

最佳答案

这很微妙。 case 正在检查 Either String (a, ParseState) 类型的值,因此当您在

中命名模式时
err@(Left _) -> err

err 具有相同的类型。但是,该函数的返回类型表明它应该是一个 Either String a,它与 errEither String (a, ParseState) 类型不匹配。查看Left的类型:

Left :: x -> Either x y

当你在右侧使用Left

Left err -> Left err

你给它一个机会选择一个不同的 y,即 a 而不是 (a, ParseState)

所以即使 values 相同,types 也不同,所以它们不能被替换。

顺便说一句,Control.Arrow 中有一些非常方便的函数(为了简单起见,专门用于 (->)):

left :: (a -> a') -> Either a b -> Either a' b
right :: (b -> b') -> Either a b -> Either a b'
(+++) :: (a -> a') -> (b -> b') -> Either a b -> Either a' b'

其语义由自由定理固定(请阅读:它们只有一个合理的实现,因此它们可以满足您对它们的类​​型的期望)。所以你可以把你的代码写成:

parse parser = right fst . runParse parser . ParseState

关于syntax - 'err@(Left _)'和 'Left err'有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4182223/

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