在模板haskell中执行类型相等 [英] Performing type equality in template haskell

查看:117
本文介绍了在模板haskell中执行类型相等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

模板Haskell 中有一个函数,它提取记录构造函数总和的类型信息,如下所示:

  listFields :: Name  - > Q([[String,Name,Type]]])
listFields name = do
TyConI(DataD _ _ _ cons _)< - reify name
let showClause(RecC conName fields )=(map(\(x,_,t) - >(nameBase $ x,x,t))fields)
return $ map showClause cons

如果给定字段的类型,那么如何将该类型的等式与特定的类型比如 GHC.Base.String Data.Text.Internal.Text ?我在 TH 文档中看到 TypeQ 。它构建了类型表达式。但是,我找不到任何关于如何构建特定类型的文档,例如 String 或 Text Int ,以便我可以使用它进行等式比较?将欣赏指针如何做到这一点,特别是如何获得特定类型的AST。

这个问题的原因是给定记录构造函数,我们想要转换每个字段为 Text 。但是, show 和 pack 对于字符串 Text 类型。因此,如果类型为 Text (不转换)或 String (仅调用<$ c),则需要生成不同的拼接$ c> pack ,不要调用 show )或别的东西(调用 pack。show 假设显示实例存在)。

解决方案

在另一个答案中,这里有一些可以让你在没有任何重叠实例的情况下编写ToText。它使用我最喜欢的技巧 - 将封闭类型族与datakinds混合在一起,作为具有典型类型类的选择机制(注意:即使使用函数依赖关系,更少重叠实例)来合成实际代码:

  { - #LANGUAGE TypeFamilies,DataKinds,MultiParamTypeClasses,FlexibleInstances,ScopedTypeVariables,FlexibleContexts# - } 

导入Data.List
import Data.Text(unpack,pack,Text)
import Data.Proxy

data ToTextMethod = TTMChar | TTMString | TTMText | TTMShow

type family ToTextHow a where
ToTextHow Char = TTMChar
ToTextHow String = TTMString
ToTextHow Text = TTMText
ToTextHow a = TTMShow

class ToTextC ab其中
toTextC :: a - > b - >文本

实例显示a => ToTextC a(Proxy TTMShow)其中
toTextC a _ = pack(显示a)

实例ToTextC Char(代理TTMChar)其中
toTextC c _ = pack [c]

实例ToTextC字符串(代理TTMString)其中
toTextC s _ =包s

实例ToTextC文本(代理TTMText)其中
toTextC t _ = t

toText :: forall a。 (Show a,ToTextC a(Proxy(ToTextHow a)))=> a - > Text
toText x = toTextC x(Proxy :: Proxy(ToTextHow a))

名字可能会使用一些工作,并且将参数翻到 toTextC 可能会很好,但是这一切在ghc 7.8.3中都可以使用。


I have a function in Template Haskell that extracts the type information for sum of record constructors as below:

listFields :: Name -> Q ([[(String,Name,Type)]])
listFields name = do
  TyConI (DataD _ _ _ cons _) <- reify name  
  let showClause (RecC conName fields) = (map (\(x,_,t) -> (nameBase $ x,x,t)) fields)
  return $ map showClause cons

Given the type in there for a field, how do you compare equality of that type with a particular type like GHC.Base.String or Data.Text.Internal.Text? I see TypeQ in TH documentation. It builds type expression. However, I can't find any documentation on how to build a particular type like String or Text or Int so that I can use it for equality comparison? Will appreciate pointers on how to do this, especially how to get the AST for a particular type.

The reason for this question is that given record constructor, we want to convert each field to Text. However, show and pack should be called differently for String and Text types. So, need to generate different splices if the type is Text (no conversion) or String (only call pack, don't call show) or something else (call pack . show assuming Show instance exists).

解决方案

As a follow-on to the other answer, here's something that lets you write ToText without any overlapping instances. It uses my new favorite trick -- mixing closed type families over datakinds as a "choice" mechanism with typical type classes (note: not even using functional dependencies, much less overlapping instances) to synthesize the actual code:

{-# LANGUAGE TypeFamilies, DataKinds, MultiParamTypeClasses, FlexibleInstances, ScopedTypeVariables, FlexibleContexts #-}

import Data.List
import Data.Text (unpack, pack, Text)
import Data.Proxy

data ToTextMethod = TTMChar | TTMString | TTMText | TTMShow

type family ToTextHow a where
     ToTextHow Char = TTMChar
     ToTextHow String = TTMString
     ToTextHow Text = TTMText
     ToTextHow a = TTMShow

class ToTextC a b where
      toTextC :: a -> b -> Text

instance Show a => ToTextC a (Proxy TTMShow) where
      toTextC a _ = pack (show a)

instance ToTextC Char (Proxy TTMChar) where
      toTextC c _ = pack [c]

instance ToTextC String (Proxy TTMString) where
      toTextC s _ = pack s

instance ToTextC Text (Proxy TTMText) where
      toTextC t _ = t

toText :: forall a. (Show a, ToTextC a (Proxy (ToTextHow a))) => a -> Text
toText x = toTextC x (Proxy :: Proxy (ToTextHow a))

The names could probably use some work, and it might be nice to flip the arguments to toTextC, but this all works even in ghc 7.8.3.

这篇关于在模板haskell中执行类型相等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆