如何解决类型变量 r 已超出其作用域
我有一个拼图的类型同义词,定义如下:
type Cell = Int
type Board = Array Cell
type Puzzle = forall r.
{ board::Board,meta::
{ metaData :: {|r},metaBoard :: (Array {|r})
}
}
我还提出了一个想法,即策略需要一个拼图并将其返回包装在三个状态之一中
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
时,您可以选择类型 r
,然后变量 p
必须以某种方式“变成”该类型,表示 p.meta.metaData :: {|r}
。
每次访问变量 p
时都会发生这种情况。每次您选择某种类型 r
时(这些每次都可能是不同的类型),并且每次字段 p.meta.metaData
都必须是该类型。
很明显,这行不通。很明显,这不是你的意思。
forall
的意思是“我将为所有类型工作”——字面意思就是名称。消费者选择哪种类型,而不是实施者。
您可能的意思是让 Puzzle
带有类型参数,这样创建 Puzzle
实例的人都可以选择当时的类型,然后选择 {{1} 的实例} 将继续使用该类型。
这样做的语法是这样的:
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
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。