Purescript 将 class 视为循环类型同义词
Purescript treats class as circular type synonym
我正在尝试定义仅适用于类型级自然数的实例。当我编译这个文件时:
module Main where
data NatZero
data NatSucc n
class NatClass n where
switch :: f NatZero -> (forall m. NatClass m => f (NatSucc m)) -> f n
它告诉我:
Error found:
at src/Main.purs:6:1 - 7:73 (line 6, column 1 - line 7, column 73)
A cycle appears in the definition of type synonym NatClass
Cycles are disallowed because they can lead to loops in the type checker.
Consider using a 'newtype' instead.
为什么 NatClass 成为类型同义词?我还以为是class类型呢。哪里有循环?我应该更改什么才能使它像 Haskell 中那样工作?它告诉我要输入新类型,我要输入什么?
该错误消息具有误导性和不幸性 - 这不是您对此处代码做错的任何事情,而是由于编译器如何对 classes 进行脱糖处理。
目前字典被表示为一条记录,所以这里错误中提到的同义词是因为编译器为 class 创建了类似这样的东西:
type NatClass n =
{ switch :: forall f. f NatZero -> (forall m. NatClass m => f (NatSucc m)) -> f n }
这样它就可以用字典参数相当直接地替换约束。
我认为现在这个 class(或任何将其自身用作成员约束的对象)会遇到同样的问题。
一段时间以来,我一直想更改类型 classes 的表示形式,并为它准备了一个 WIP PR,我认为之后这种事情将被允许。在此之后 classes 将被脱糖为 data
类型而不是同义词,因此应该允许引用。
您可以通过自己具体化字典来轻松解决 Purescript 限制。像 -
data NatZero
data NatSucc n
newtype NatClassDict n = NatClassDict (forall f. f NatZero -> (forall m. NatClass m => f (NatSucc m)) -> f n)
getSwitch :: NatClassDict n -> (forall f. f NatZero -> (forall m. NatClass m => f (NatSucc m)) -> f n)
getSwitch (NatClassDict f) = f
class NatClass n where
natClassDict :: NatClassDict n
switch :: NatClass n => forall f. f NatZero -> (forall m. NatClass m => f (NatSucc m)) -> f n
switch = getSwitch natClassDict
我正在尝试定义仅适用于类型级自然数的实例。当我编译这个文件时:
module Main where
data NatZero
data NatSucc n
class NatClass n where
switch :: f NatZero -> (forall m. NatClass m => f (NatSucc m)) -> f n
它告诉我:
Error found:
at src/Main.purs:6:1 - 7:73 (line 6, column 1 - line 7, column 73)
A cycle appears in the definition of type synonym NatClass
Cycles are disallowed because they can lead to loops in the type checker.
Consider using a 'newtype' instead.
为什么 NatClass 成为类型同义词?我还以为是class类型呢。哪里有循环?我应该更改什么才能使它像 Haskell 中那样工作?它告诉我要输入新类型,我要输入什么?
该错误消息具有误导性和不幸性 - 这不是您对此处代码做错的任何事情,而是由于编译器如何对 classes 进行脱糖处理。
目前字典被表示为一条记录,所以这里错误中提到的同义词是因为编译器为 class 创建了类似这样的东西:
type NatClass n =
{ switch :: forall f. f NatZero -> (forall m. NatClass m => f (NatSucc m)) -> f n }
这样它就可以用字典参数相当直接地替换约束。
我认为现在这个 class(或任何将其自身用作成员约束的对象)会遇到同样的问题。
一段时间以来,我一直想更改类型 classes 的表示形式,并为它准备了一个 WIP PR,我认为之后这种事情将被允许。在此之后 classes 将被脱糖为 data
类型而不是同义词,因此应该允许引用。
您可以通过自己具体化字典来轻松解决 Purescript 限制。像 -
data NatZero
data NatSucc n
newtype NatClassDict n = NatClassDict (forall f. f NatZero -> (forall m. NatClass m => f (NatSucc m)) -> f n)
getSwitch :: NatClassDict n -> (forall f. f NatZero -> (forall m. NatClass m => f (NatSucc m)) -> f n)
getSwitch (NatClassDict f) = f
class NatClass n where
natClassDict :: NatClassDict n
switch :: NatClass n => forall f. f NatZero -> (forall m. NatClass m => f (NatSucc m)) -> f n
switch = getSwitch natClassDict