purescript - 类型变量 r 已超出其范围
问题描述
我有一个拼图的类型同义词,如下所示:
type Cell = Int
type Board = Array Cell
type Puzzle = forall r.
{ board::Board
, meta::
{ metaData :: {|r}
, metaBoard :: (Array {|r})
}
}
我还包含了这样一个想法,即一个策略需要一个 Puzzle 并将其返回为三种状态之一
type Strategy = Puzzle -> (Stateful Puzzle)
data Stateful a =
Advancing a
| Stable a
| Finished a
最后,我有一个函数可以让我们(有点)了解它的Either
工作原理。这个想法是最终我可以开始编写策略,直到达到完成状态。
advanceOrFinish :: (Stateful Puzzle) -> (Stateful Puzzle)
advanceOrFinish (Advancing puzzle)
| isSolvedOrInvalid puzzle.board = Finished puzzle
| otherwise = Advancing puzzle
advanceOrFinish (Stable puzzle)
| isSolvedOrInvalid puzzle.board = Finished puzzle
| otherwise = Advancing puzzle
advanceOrFinish (Finished puzzle) = Finished puzzle
问题是我收到了这个错误:
The type variable r, bound at
src/SC.purs:23:15 - 29:4 (line 23, column 15 - line 29, column 4)
has escaped its scope, appearing in the type
{ board :: Array Int
, meta :: { metaBoard :: Array (Record r7)
, metaData :: Record r7
}
}
Stateful
没有(虽然没用)的相同功能没有这个问题。所以这很好:
advanceOrFinish :: Puzzle -> Puzzle
advanceOrFinish puzzle
| isSolvedOrInvalid puzzle.board = puzzle
| otherwise = puzzle
这个错误想告诉我什么?
解决方案
type Puzzle = forall r. ...
并不意味着你认为它意味着什么。
如果你有一个变量:
p :: Puzzle
然后你想用那个变量做一些事情,比如:
b = p.board
在那一刻,当您p
通过名称引用时,您可以选择一个 type r
,然后该变量p
必须以某种方式“变成”该类型,这意味着p.meta.metaData :: {|r}
.
每次访问变量时都会发生这种情况p
。每次您选择某种类型r
(每次可能是不同的类型),并且每次该字段p.meta.metaData
都必须是该类型。
很明显,这不能合理地工作。很明显,这不是你的意思。
forall
意思是“我将为所有类型工作” - 这就是名字的字面意思。消费者选择哪种类型,而不是实施者。
您可能的意思是Puzzle
使用带有类型参数的 a,以便创建 的实例的人Puzzle
可以在那一刻选择类型,然后 的实例Puzzle
将继续使用该类型。
这样做的语法是这样的:
type Puzzle r =
{ board::Board
, meta::
{ metaData :: {|r}
, metaBoard :: (Array {|r})
}
}
这里r
称为“类型参数” Puzzle
。
然后,每当您提及 时Puzzle
,您都必须说明r
这种情况是什么,例如:
foo :: Puzzle (a :: Int) -> Int
foo p = p.meta.metaData.a
bar :: Puzzle (x :: String) -> Unit
bar _ = unit
如果你不在乎它是什么,它也可以是通用的:
advanceOrFinish :: forall r. Puzzle r -> Puzzle r
advanceOrFinish puzzle
| isSolvedOrInvalid puzzle.board = puzzle
| otherwise = puzzle
推荐阅读
- python-3.x - Imagemagick 转换不转换
- javascript - chrome.contextmenus 如何获取 html 而不是字符串
- java - 我认为 Stream.filter() 即使使用无效的谓词也没有显示编译时错误
- javascript - 隐藏一个元素并在提交表单时显示另一个元素
- java - For循环导致窗口弹出的次数比预期的多
- angular - 如何将包含指令的 HTML 动态插入到 Angular 2 模板中?
- python - x 轴框架大小完全相同的两个图形
- django - Django:表单集的动态选择字段
- html - 在表格的每一行下方放置内容
- javascript - 与 .flat() 相反的 JavaScript