我最近在Haskell中一直将refined用于细化类型,并且遇到了主要的可用性问题。我无法弄清楚如何在编译时优化整个值列表。
例如,我可以写:
{-# LANGUAGE TemplateHaskell #-}
import Refined
oneToThree :: [Refined Positive Int]
oneToThree = [$$(refineTH 1), $$(refineTH 2), $$(refineTH 3)]
但是我不能这样做,不能使用范围语法,因为Refined
没有(出于充分的理由)没有Enum
的实例。
我希望能够做类似的事情
oneToThree :: [Refined Positive Int]
oneToThree = $$(refineTH <$> [1..3])
但是由于无法将[TExp (Refined Positive Int)]
提升到TExp [Refined Positive Int]
,所以我无法编译它。
是否有我缺少的模板haskell魔术能让我做到这一点?
如果有人提出建议,也将接受关于更好的轻量级精炼类型库的建议。
此方法有效(由于阶段限制,它必须与您使用的文件位于不同的文件中:]
import Language.Haskell.TH.Syntax (Exp(ListE), TExp(TExp))
makeTypedTHList :: [TExp a] -> TExp [a]
makeTypedTHList xs = TExp $ ListE [x | TExp x <- xs]
然后您将像这样使用它:
{-# LANGUAGE TemplateHaskell #-}
import Refined
import AboveCodeInSeparateModuleBecauseOfStageRestriction (makeTypedTHList)
oneToThree :: [Refined Positive Int]
oneToThree = $$(makeTypedTHList <$> traverse refineTH [1..3])
但是,自己调用TExp
构造函数会破坏类型化的模板Haskell的某些安全性(尽管我认为这种特殊情况是安全的)。理想情况下,我更喜欢一种不需要这样做的方法,但我想不到一个。