标签: template-haskell

Haskell反省了记录的字段名称和类型

基于最近的交换,我已经确信使用Template Haskell生成一些代码来确保编译时类型的安全性.

我需要内省记录字段名称和类型.我知道我可以通过使用获得字段名称constrFields . toConstr :: Data a => a -> [String].但我需要的不仅仅是字段名称,我需要知道它们的类型.例如,我需要知道类型字段的名称Bool.

如何构建函数f :: a -> [(String, xx)]where athe record,String是字段名称xx还是字段类型?

haskell template-haskell

9
推荐指数
1
解决办法
816
查看次数

使用Template Haskell在编译时评估函数

我正在编写一个简单的HashString类,它只是一个字符串及其哈希:

data HashString = HashString Int    -- ^ hash
                             T.Text -- ^ string!
Run Code Online (Sandbox Code Playgroud)

现在我正在尝试在编译时使用以下内容生成这些:

$(hString "hello, world") :: HashString
Run Code Online (Sandbox Code Playgroud)

我想要哈希,文本打包在编译时发生.我该怎么做呢?

这是我到目前为止所尝试的,但我不确定它是否正确,我也不确定它是否在编译时完成了所有工作:

hString :: String -> Q Exp
hString s = [| HashString (hash $ T.pack s) (T.pack s) |]
Run Code Online (Sandbox Code Playgroud)

haskell template-haskell

9
推荐指数
1
解决办法
1181
查看次数

如何规避GHC阶段限制?

我正在编写一个代码生成器,其输出依赖于存储在其类实例中的数据类型字段描述.但是,我找不到如何使用TH生成的参数运行函数.

{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}
module Generator where
import Language.Haskell.TH
import Language.Haskell.TH.Syntax

data Description = Description String [Description] deriving Show

class HasDescription a where
  getDescription :: a -> Description

instance HasDescription Int where
  getDescription _ = Description "Int" []

instance (HasDescription a, HasDescription b) => HasDescription (a, b) where
  getDescription (_ :: (a, b)) = Description "Tuple2" [getDescription (undefined :: a), getDescription (undefined :: b)]

-- | creates instance of HasDescription for the passed datatype changing descriptions of its …
Run Code Online (Sandbox Code Playgroud)

haskell template-haskell

9
推荐指数
2
解决办法
1304
查看次数

在编译时或运行时生成随机字符串,并在程序的其余部分中使用它

最好的方法是什么?unsafePerformIO?模板Haskell?别的什么?我从来没有使用过这些,所以我不知道使用它们的许多细节.

请注意,程序将在每次运行时进行编译,因此在编译时或运行时生成字符串无关紧要.我还需要在整个代码中的大量位置使用此字符串,因此我无法以"正确"方式执行此操作并将其作为IO操作,这将需要将太多其他代码放入IO monad中.

io haskell template-haskell unsafe-perform-io

9
推荐指数
3
解决办法
3264
查看次数

模板Haskell:如何提取函数的参数个数?

我有一个函数给出了Name一个函数它增加它,产生另一个函数应用于其他一些东西(细节不太相关):

mkSimple :: Name -> Int -> Q [Dec]
mkSimple adapteeName argsNum = do
  adapterName <- newName ("sfml" ++ (capitalize . nameBase $ adapteeName))
  adapteeFn <- varE adapteeName
  let args = mkArgs argsNum
  let wrapper = mkApply adapteeFn (map VarE args)
  -- generates something like SFML $ liftIO $ ((f a) b) c)
  fnBody <- [| SFML $ liftIO $ $(return wrapper) |]
  return [FunD adapterName [Clause (map VarP args) (NormalB fnBody) []]]

  where
    mkArgs :: Int -> …
Run Code Online (Sandbox Code Playgroud)

haskell template-haskell

9
推荐指数
1
解决办法
538
查看次数

在记录上映射身份仿函数

我有一个像这样的记录类型:

data VehicleState f = VehicleState
                      {
                        orientation :: f (Quaternion Double),
                        orientationRate :: f (Quaternion Double),
                        acceleration :: f (V3 (Acceleration Double)),
                        velocity :: f (V3 (Velocity Double)),
                        location :: f (Coordinate),
                        elapsedTime :: f (Time Double)
                      }
                    deriving (Show)
Run Code Online (Sandbox Code Playgroud)

这很酷,因为我可以拥有VehicleState Signal各种各样的元数据,我可以拥有每个信号VehicleState (Wire s e m ())netwire语义,或者我可以VehicleState Identity在某个时间观察实际值.

有没有一种很好的方法来在每个字段之间来回映射VehicleState IdentityVehicleState'定义runIdentity

data VehicleState' = VehicleState'
                      {
                        orientation :: Quaternion Double,
                        orientationRate :: Quaternion Double,
                        acceleration :: …
Run Code Online (Sandbox Code Playgroud)

haskell functor template-haskell

9
推荐指数
1
解决办法
286
查看次数

"模板Haskell + C"错误的解决方法?

我有以下情况:

  • 库X是C中一些代码的包装器.
  • 库A取决于库X.
  • 库B使用模板Haskell并依赖于库A.

GHC bug#9010使用GHC 7.6无法安装库B. 处理TH时,GHCi会启动并尝试加载库X,这会失败并显示消息

Loading package charsetdetect-ae-1.0 ... linking ... ghc:
~/.cabal/lib/x86_64-linux-ghc-7.6.3/charsetdetect-ae-1.0/
libHScharsetdetect-ae-1.0.a: unknown symbol `_ZTV15nsCharSetProber'
Run Code Online (Sandbox Code Playgroud)

("未知符号"的实际名称因机器而异).

有没有解决这个问题的方法(当然除了"不要使用模板Haskell")?也许库X必须以不同的方式编译,或者有一些方法可以阻止它加载(因为它不应该在代码生成期间调用)?

haskell ghc template-haskell

9
推荐指数
1
解决办法
396
查看次数

在编写重载字符串时如何删除样板?

给出以下代码:

{-# LANGUAGE OverloadedStrings #-}

newtype Firstname = Firstname String deriving (Eq, Show)
instance IsString Firstname where fromString = Firstname

newtype Lastname = Lastname String deriving (Eq, Show)
instance IsString Lastname where fromString = Lastname

data Person = Person { firstname :: Firstname, lastname :: Lastname, age :: Int } deriving Show
Run Code Online (Sandbox Code Playgroud)

我想删除围绕创建强类型字符串的样板.有可能使用Template Haskell(或其他一些方法)来实现这一目标吗?

例如:

{-# LANGUAGE OverloadedStrings, TemplateHaskell #-}

$(strongString ''Firstname)
$(strongString ''Lastname)

data Person = Person { firstname :: Firstname, lastname :: Lastname, age :: Int } deriving …
Run Code Online (Sandbox Code Playgroud)

haskell template-haskell

8
推荐指数
1
解决办法
624
查看次数

使用自定义名称处理器为"镜头"库生成镜头,而不是默认的"下划线"库

标准makeLenses实现为记录的所有字段生成镜头,以下划线开头.出于多种原因,我非常不喜欢将这种尴尬的命名约定引入我的记录.我想要做的只是为记录的所有字段生成镜头,并通过在字段名称后附加后缀"L"来命名它们.

有了fc标签库,我必须做的就是实现这一目标

mkLabelsWith (++ "L") [''MyRecord]
Run Code Online (Sandbox Code Playgroud)

但是镜头库有一个更复杂的配置,包括规则集和内容,这并不容易让人大开眼界.所以我要求一个特定的配方来实现同样的目的.

haskell template-haskell lenses haskell-lens

8
推荐指数
2
解决办法
678
查看次数

带参数的QuasiQuote

我想在Haskell中写一个引文.name参数需要传递给gen函数以生成声明.

quote ::  String -> QuasiQuoter
quote name = QuasiQuoter {
       quoteExp = undefined,
       quotePat = undefined,
       quoteType = undefined,
       quoteDec = \jsonStr -> gen name (getValue str)
     }
Run Code Online (Sandbox Code Playgroud)

但是,似乎我不能像这样使用报价

[quote "Hello"| from x to y |]
Run Code Online (Sandbox Code Playgroud)

由于Haskell不允许引用声明和引用在同一个令人烦恼的文件中,我该怎样做才能将参数从外部传递到引用中?

haskell template-haskell

8
推荐指数
1
解决办法
491
查看次数