gpt4 book ai didi

haskell 错误 : Could not deduce (Random a0)

转载 作者:行者123 更新时间:2023-12-03 19:16:13 25 4
gpt4 key购买 nike

我正在尝试创建另一个 Random 实例,但遇到了类型错误。我将其简化为以下 ghci session :

GHCi, version 8.6.5:
λ> import System.Random
λ> :t random
random :: (Random a, RandomGen g) => g -> (a, g)
λ> :t \g -> random g
\g -> random g :: (Random a, RandomGen g) => g -> (a, g)
λ> :t \g -> let xh = random g in xh
\g -> let xh = random g in xh
:: (Random a, RandomGen g) => g -> (a, g)
λ> :t \g -> let (x, h) = random g in (x, h)

<interactive>:1:11: error:
• Could not deduce (Random a0)
from the context: (Random a, RandomGen b)
bound by the inferred type of
it :: (Random a, RandomGen b) => b -> (a, b)
at <interactive>:1:1
The type variable ‘a0’ is ambiguous
• When checking that the inferred type
h :: forall a. Random a => b
is as general as its inferred signature
h :: b
In the expression: let (x, h) = random g in (x, h)
In the expression: \ g -> let (x, h) = ... in (x, h)

为什么上个版本会失败?

最佳答案

这是一个可爱的问题。您可能会想象这会被翻译成像这样的显式字典传递样式:

-- original
foo = \g -> let (x, h) = random g in (x, h)

-- assumed but incorrect explicit version
foo = /\a. /\b. \\(da :: Random a) => \\(db :: RandomGen b) =>
\(g :: b) -> let tmp = random @a @b ,da ,db g
x = case tmp of (x, h) -> x
h = case tmp of (x, h) -> h
in (x, h)

这里我使用了一些自定义的新语法:

  • /\ty。 tm 是显式类型抽象;它接受一个类型,将其命名为 ty,并按照术语 tm 的方式进行
  • tm @ty 是显式类型应用;它采用多态项 tm 并提供 ty 作为第一个类型参数
  • \\(dict::c) => tm 是明确的类型类抽象;它采用作为约束 c 证据的类型类字典,将其命名为 dict,并像术语 tm 一样继续
  • tm ,dict 是显式类型类应用;它接受一个假定某个类型类实例的术语,并提供字典 dict 作为该实例的证据

如果这就是编译的方式,那么就不会有歧义,\g -> let (x, h) = random g in (x, h) 只会与前面所有术语的类型相同。但这并不是模式绑定(bind)的实际编译方式,因为这使得 xh 的类型比它们需要的更具限制性。相反,它是这样编译的:

-- actual explicit version
foo = /\a. /\b. /\c. \\(da :: Random a) => \\(db :: Random b) => \\(dc :: RandomGen c) =>
\(g :: b) -> let x = /\d. \\(dd :: Random d) =>
case random @d @c ,dd ,dc g of (x, h) -> x
h = /\d. \\(dd :: Random d) =>
case random @d @c ,dd ,dc g of (x, h) -> h
in (x @a ,da , h @b ,db)

这个是更多态,因为在计算 x 时用于选择 Random 实例的类型与用于选择的类型无关在计算 h 时选择一个 Random 实例。在这种情况下,这不是您想要的;但是可以设想其他情况,这正是您想要的,并且将这两种类型捆绑在一起对于表达您想要的计算非常不方便。

但是,由于这种翻译允许额外的灵 active ,我们发现自己在这里有点困难:这个东西的调用者如何影响为 b 选择的类型并不那么明显(因此 db 使用哪个字典),因为 b 没有出现在整个类型的任何地方!所以编译器给你一个类型歧义错误。作为一个直观的解释:我们知道要使用哪个 Random 实例来计算 x,因为调用者必须为元组的第一部分选择一个类型;但是我们不知道要使用哪个实例来计算 h,因为为 h 选择类型并不能确定要为丢弃的 x< 使用什么类型 计算的一半用于定义 h

您可以通过启用 MonoLocalBinds 扩展要求编译器选择第一个翻译。您可以阅读更多相关信息 here .它有时会阻止 let 绑定(bind)以上述方式变为多态,这意味着类型推断将有更多线索,但一些其他可接受的程序将不再进行类型检查。

关于 haskell 错误 : Could not deduce (Random a0),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60493352/

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