首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何通过编程将[TExp a]转换为TExp [a],或者以其他方式将refineTH应用于多个值?

如何通过编程将[TExp a]转换为TExp [a],或者以其他方式将refineTH应用于多个值?
EN

Stack Overflow用户
提问于 2020-03-10 23:54:47
回答 2查看 81关注 0票数 2

最近,我一直在Haskell中使用精练进行细化类型,并且遇到了一个主要的可用性问题。我不知道如何在编译时细化整个值列表。

例如,我可以写:

代码语言:javascript
复制
{-# LANGUAGE TemplateHaskell #-}

import Refined

oneToThree :: [Refined Positive Int]
oneToThree = [$$(refineTH 1), $$(refineTH 2), $$(refineTH 3)]

但是我不能这样做,因为Refined没有(出于很好的理由)有一个Enum实例,所以不能使用范围语法。

我希望能做些像

代码语言:javascript
复制
oneToThree :: [Refined Positive Int]
oneToThree = $$(traverse refineTH [1..3])

但是我无法编译它,因为我不能将[TExp (Refined Positive Int)]提升到TExp [Refined Positive Int]中。

有没有我错过的模板haskell魔法可以让我这么做?

如果有人有建议的话,也可以接受更好的轻量级精化类型库的建议。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-11 01:56:05

代码语言:javascript
复制
sequenceQTExpList :: [Q (TExp a)] -> Q (TExp [a])
sequenceQTExpList [] = [|| [] ||]
sequenceQTExpList (x:xs) = [|| $$(x) : $$(sequenceQTExpList xs) ||]

然后用它作为

代码语言:javascript
复制
$$(sequenceQTExpList $ map refineTH [1..3])

你说得对,这感觉就像一次穿越。但是,类型有点不一样,额外的Q在周围浮动。我没有看到任何可以让你有效地组合这些层的随意的东西。

不幸的是,这里使用的很多机制都是TH语法,而不是函数。只是没有一种明显的方法可以同时完成提升和剪接作为函数,所以您只能为每种容器类型编写定制助手,而不是使用Traversable。这是个有趣的问题。如果有一个干净的解决方案,它将很有可能使它成为未来版本的模板Haskell,如果它是向维护人员提出的。但我现在看不出来。

票数 3
EN

Stack Overflow用户

发布于 2020-03-11 01:37:29

这是可行的(但由于阶段限制,它必须位于与您使用的文件不同的文件中):

代码语言:javascript
复制
import Language.Haskell.TH.Syntax (Exp(ListE), TExp(TExp))

makeTypedTHList :: [TExp a] -> TExp [a]
makeTypedTHList xs = TExp $ ListE [x | TExp x <- xs]

然后你会像这样使用它:

代码语言:javascript
复制
{-# LANGUAGE TemplateHaskell #-}

import Refined
import AboveCodeInSeparateModuleBecauseOfStageRestriction (makeTypedTHList)

oneToThree :: [Refined Positive Int]
oneToThree = $$(makeTypedTHList <$> traverse refineTH [1..3])

但是,自己调用TExp构造函数会破坏类型化模板Haskell的一些安全性(尽管我认为这种情况是安全的)。理想情况下,我更喜欢一种不需要这样做的方法,但我想不出其中一种。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60627472

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档