gpt4 book ai didi

haskell - 创建有效构造函数列表

转载 作者:行者123 更新时间:2023-12-03 15:06:29 25 4
gpt4 key购买 nike

考虑以下:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GADTs #-}

data T = T1 | T2

data D (t :: T) where
D1 :: D T1
D2 :: D T2
D3 :: D d
D4 :: D T1

x1 :: [D T1]
x1 = [D1, D3, D4]

x2 :: [D T2]
x2 = [D2, D3]

基本上 x1D T1 的所有有效构造函数的列表, 和 x2D T2 的所有有效构造函数的列表.

但是,我希望这两个列表都反射(reflect)添加到 D 中的任何其他构造函数。 ,我不想像现在这样对这些列表进行硬编码。

有没有办法定义 x1x2这样它们是从 D 自动生成的?

最佳答案

免责声明 - 我的 TemplateHaskell-fu 几乎不存在 - 但我已经进行了一些调查,这应该给你一个开始工作的起点:

对于那些不知道 Template Haskell 是一种元编程(语言)的人,它允许编写在编译时运行的程序 - 它经过类型检查,所以它是安全的(对于安全的某些定义,我认为你可以编写需要无限时间编译的程序)。

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TemplateHaskell #-}

import Language.Haskell.TH

data T = T1 | T2

data D (t :: T) where
D1 :: D T1
D2 :: D T2
D3 :: D d
D4 :: D T1

您可以首先将文件加载到 GHCi 中(不要忘记 :set -XTemplateHaskell 那里)
> typeInfo = reify ''D
> $(stringE . show =<< typeInfo)
typeInfo 是一个 Q Info ,允许您从类型中提取信息(由 '' 转义) - $(..) 的工作方式类似于打印。

这为您提供了构建 (G)ADT 的模板 haskell 表达式:
TyConI (
DataD [] TMP.D [KindedTV t_6989586621679027167 (ConT TMP.T)] Nothing
[GadtC [TMP.D1] [] (AppT (ConT TMP.D) (ConT TMP.T1))
,GadtC [TMP.D2] [] (AppT (ConT TMP.D) (ConT TMP.T2))
,ForallC [KindedTV d_6989586621679027168 (ConT TMP.T)] [] (GadtC [TMP.D3] [] (AppT (ConT TMP.D) (VarT d_6989586621679027168)))
,GadtC [TMP.D4] [] (AppT (ConT TMP.D) (ConT TMP.T1))] [])

我进行了一些模式匹配 - 你可以找到没有限制( ForallC )或特定类型( TMP.T1/ TMP.T2 )的构造函数,然后编写一些表达式 - 从中​​创建一个新类型。

现在我没有足够的时间来提供这个 - 但我今晚会更新这个答案。

编辑

我在构造类型方面看了更多,但我不得不承认我自己有点卡住了——我成功地解构了类型信息。
d = reify ''D

dataName :: Info -> Maybe [Name]
dataName (TyConI (DataD _ _ _ _ x _) )= Just [t | NormalC t _ <- x]
dataName _ = Nothing

gadtDataUnsafe :: Info -> Q Exp
gadtDataUnsafe (TyConI (DataD _ _ _ _ cons _)) = return $ head $ concat [t | GadtC t _ _ <- cons]

我认为从这里过滤 T1/ T2/ forall d 是可行的,虽然乏味但可以构建列表。

我失败的是构造类型 - 如果我将文件加载到 ghci 我可以执行
> f = $(gadtDataUnsafe =<< d)
>:t f
f :: D 'T1

但是如果我在文件中调用它,我会收到以下错误
error:
• GHC stage restriction:
‘gadtData’ is used in a top-level splice, quasi-quote, or annotation,
and must be imported, not defined locally
• In the untyped splice: $(gadtData =<< d)

我知道,例如,Edward Kmett 为东西制作了一些 th-magic 创建镜头,并且它在同一个文件中工作,但拼接没有分配给变量 - 所以也许你需要在 Q Exp 内为你的列表构建名称 -我想 mkName 会是你需要的东西。

这总结了我发现的所有内容 - 我希望它有所帮助,我至少学到了一些东西 - 对于完整的答案,也许更聪明/更有经验的模板 haskell 可以在第二个答案中提供他/她的一些知识。

关于haskell - 创建有效构造函数列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43532911/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com