微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

来自 Prim.Union 的 ConstrainedTypeUnified 错误

如何解决来自 Prim.Union 的 ConstrainedTypeUnified 错误

我想将 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)

有关这方面的更多信息,请查看我不久前写的 this answer

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。