我正在编写一个简单的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) 我正在编写一个代码生成器,其输出依赖于存储在其类实例中的数据类型字段描述.但是,我找不到如何使用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) 最好的方法是什么?unsafePerformIO?模板Haskell?别的什么?我从来没有使用过这些,所以我不知道使用它们的许多细节.
请注意,程序将在每次运行时进行编译,因此在编译时或运行时生成字符串无关紧要.我还需要在整个代码中的大量位置使用此字符串,因此我无法以"正确"方式执行此操作并将其作为IO操作,这将需要将太多其他代码放入IO monad中.
我有一个函数给出了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) 我有一个像这样的记录类型:
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 Identity和VehicleState'定义runIdentity?
data VehicleState' = VehicleState'
{
orientation :: Quaternion Double,
orientationRate :: Quaternion Double,
acceleration :: …Run Code Online (Sandbox Code Playgroud) 我有以下情况:
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必须以不同的方式编译,或者有一些方法可以阻止它加载(因为它不应该在代码生成期间调用)?
给出以下代码:
{-# 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) 标准makeLenses实现为记录的所有字段生成镜头,以下划线开头.出于多种原因,我非常不喜欢将这种尴尬的命名约定引入我的记录.我想要做的只是为记录的所有字段生成镜头,并通过在字段名称后附加后缀"L"来命名它们.
有了fc标签库,我必须做的就是实现这一目标
mkLabelsWith (++ "L") [''MyRecord]
Run Code Online (Sandbox Code Playgroud)
但是镜头库有一个更复杂的配置,包括规则集和内容,这并不容易让人大开眼界.所以我要求一个特定的配方来实现同样的目的.
我想在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不允许引用声明和引用在同一个令人烦恼的文件中,我该怎样做才能将参数从外部传递到引用中?