来自 Prim.Union 的 ConstrainedTypeUnified 错误

ConstrainedTypeUnified error from Prim.Union

我想定义一个 Record 类型 Rec3 作为两行的并集,这样我就可以使用 Rec3 作为函数 func1 的参数。

import Prim.Row (class Union)

type Row1 = (x1 :: Int)
type Row2 = (x2 :: String)
type Rec3 = forall r. Union Row1 Row2 r => Record r

func1 :: Rec3 -> String
func1 {x1,x2} = show x1 <> x2

这似乎可以编译,但是当我添加对 func1

的调用时
func1 {x1:3,x2:"t"}
Could not match type

    r0

  with type

    ( x1 :: Int
    | t1
    )


while trying to match type r0
  with type ( x1 :: Int
            | t1
            )
while checking that expression { x1: 3
                               , x2: "t"
                               }
  has type Record r0
in value declaration main

where r0 is a rigid type variable
        bound at (line 22, column 47 - line 22, column 60)
      t1 is an unknown type

See https://github.com/purescript/documentation/blob/master/errors/ConstrainedTypeUnified.md for more information,
or to contribute content related to this error.

这可能吗?

你的forall放错地方了。

您的意思可能是 func1 的签名是这样的:

func1 :: forall r. Union Row1 Row2 r => Record r -> String

但是你声明的方式,实际上是这样的:

func1 :: (forall r. Union Row1 Row2 r => Record r) -> String

注意括号。它们很重要。

在第一个签名中,forall r适用于整个函数,也就是说谁调用函数就选择r是什么。然而,在第二个签名中,forall r 仅适用于第一个参数,这意味着无论谁试图访问该参数,都会选择 r 是什么。这意味着无论谁调用 func1 都不会选择 r,而是相反,必须以某种方式传入通用类型的记录。这当然是不可能的。


如果要合并两条记录,可以将Rec1Rec2定义为可扩展行(即带有参数),然后将其中一行作为参数传递给另一个:

type Row1 r = (x1 :: Int | r)
type Row2 = (x2 :: String)
type Rec3 = Record (Row1 Row2)

有关这方面的更多信息,请查看 我刚才写的。