是否可以使用SYB来转换类型?
我想编写一个 rename
函数,用 GUID
替换 AST
中的 String
名称(代表分层标识符)来自符号表的名称(整数)作为 Renamer monad 中的隐藏状态携带。
我有一个 AST a 类型,它通过名称类型进行参数化。 AST 叶子中的名称属于 Name a
类型:
data Name a = Name a
这使得可以轻松使用 SYB 转换器来定位它们。
解析器已键入(为简洁起见,忽略错误的可能性):
parse :: String -> AST String
并且我希望键入 rename
函数:
rename :: AST String -> Renamer (AST GUID)
是否可以使用 SYB 来转换所有 Name String
'使用转换器将其转换为 Name GUID
:
resolveName :: Name String -> Renamer (Name GUID)
以及通过转换其子项并将其粘贴回从 c String
到 c GUID
的所有其他值与相同的构造函数一起使用,尽管具有不同的类型参数?
everywhereM
函数很接近我想要的,但它只能转换 ca ->; m (ca)
而不是 ca ->米(CB)。
我的后备解决方案(除了手动编写样板之外)是从 AST
中删除类型参数,并像这样定义 Name
:
data Name = StrName String
| GuidName GUID
以便键入重命名:
rename :: AST -> Renamer AST
使其与 everywhereM
一起工作。但是,这可能会导致 AST
在重命名后仍然可以保存 StrName
。我想使用类型系统来正式捕获重命名的 AST
只能保存 GUID
名称这一事实。
I want to write a rename
function to replace String
names (which represent hierarchical identifiers) in my AST
with GUID
names (integers) from a symbol table carried as hidden state in a Renamer
monad.
I have an AST a
type that is parameterized over the type of name. Names in the leaves of the AST are of type Name a
:
data Name a = Name a
Which makes it easy to target them with a SYB transformer.
The parser is typed (ignoring the possibility of error for brevity):
parse :: String -> AST String
and I want the rename
function to be typed:
rename :: AST String -> Renamer (AST GUID)
Is it possible to use SYB to transform all Name String
's into Name GUID
's with a transformer:
resolveName :: Name String -> Renamer (Name GUID)
and all other values from c String
to c GUID
by transforming their children, and pasting them back together with the same constructor, albeit with a different type parameter?
The everywhereM
function is close to what I want, but it can only transform c a -> m (c a)
and not c a -> m (c b)
.
My fallback solution (other than writing the boiler-plate by hand) is to remove the type parameter from AST
, and define Name
like this:
data Name = StrName String
| GuidName GUID
so that the rename would be typed:
rename :: AST -> Renamer AST
making it work with everywhereM
. However, this would leave the possibility that an AST
could still hold StrName
's after being renamed. I wanted to use the type system to formally capture the fact that a renamed AST
can only hold GUID
names.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一种解决方案(可能比您希望的效率低)是让您的 AST 成为
Functor
、Data
和Typeable
的实例 (GHC 7可能可以为您导出所有这些)然后执行以下操作:两点:
resolveName
中消除Name
位,但我怀疑确实如此。universeBi
切换为 SYB 中的等效项,但我发现 Uniplate 版本更容易理解。One solution (perhaps less efficient than you were hoping for) would be to make your AST an instance of
Functor
,Data
andTypeable
(GHC 7 can probably derive all of these for you) then do:Two points:
Name
bit fromresolveName
, but I suspect it is.universeBi
for something equivalent in SYB, but I find it much easier to understand the Uniplate versions.