作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有没有办法编写以下内容:
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveAnyClass #-}
data X = A | B | C
deriving (Eq, Ord, Show, Read, Data, SymWord, HasKind, SMTValue)
deriving
子句可以以某种方式缩短,如下所示:
data X = A | B | C deriving MyOwnClass
MyOwnClass
中所示),但这并不是真的与
deriving
合作机制。通过约束种类扩展,我发现你可以这样写:
type MyOwnClass a = (Eq a, Ord a, Show a, Read a, Data a, SymWord a, HasKind a, SMTValue a)
deriving
条款。有什么魔法可以让这一切发生吗?
最佳答案
有坏而简单的方法,也有好的但困难的方法。如Silvio Mayolo说你可以用TemplateHaskell
写这样的功能。这种方式是困难且相当复杂的方式。更简单的方法是像这样使用 C 预处理器:
{-# LANGUAGE CPP #-}
#define MY_OWN_CLASS (Eq, Ord, Show, Read, Data, SymWord, HasKind, SMTValue)
data X = A | B | C
deriving MY_OWN_CLASS
deriving
-clause 不是一些独立的子句,它是
data
的一部分声明,因此您不能仅对
deriving
内的部分进行编码很遗憾。编写任何 TH 代码的一般方法是使用
runQ
括号中的命令以查看最后应该写什么。像这样:
ghci> :set -XTemplateHaskell
ghci> :set -XQuasiQuotes
ghci> import Language.Haskell.TH
ghci> runQ [d|data A = B deriving (Eq, Show)|]
[ DataD
[]
A_0
[]
Nothing
[ NormalC B_1 [] ]
[ ConT GHC.Classes.Eq , ConT GHC.Show.Show ]
]
deriving
的类型类被指定为
DataD
的最后一个参数— 数据声明 — 构造函数。您的问题的解决方法是使用
-XStadandaloneDeriving
extension .就像
deriving
但功能强大,但也很冗长。同样,要查看您想要生成的内容,只需使用
runQ
:
ghci> data D = T
ghci> :set -XStandaloneDeriving
ghci> runQ [d| deriving instance Show D |]
[ StandaloneDerivD [] (AppT (ConT GHC.Show.Show) (ConT Ghci5.D)) ]
StandaloneDerivD
和其他构造函数直接或只使用
[d|...|]
-括号虽然他们有更多的魔力,但他们给你列表
Dec
(声明)。如果要生成多个声明,则应编写如下函数:
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE StandaloneDeriving #-}
module Deriving where
import Language.Haskell.TH
boilerplateAnnigilator :: Name -> Q [Dec]
boilerplateAnnigilator typeName = do
let typeCon = conT typeName
[d|deriving instance Show $(typeCon)
deriving instance Eq $(typeCon)
deriving instance Ord $(typeCon)
|]
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
import Deriving
data X = A | B | C
boilerplateAnnigilator ''X
boilerplateAnnigilator
里面。功能。但这种方法只适用于非参数化类。如果您有
data MyData a = ...
那么独立派生应该如下所示:
deriving instance Eq a => MyData a
关于haskell - 有没有办法缩短这个派生条款?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45113205/
我是一名优秀的程序员,十分优秀!