在使用模板haskell的haskell项目中,我试图生成一个具有类型注释作为幻像类型的表达式。
一个简单的例子是package my.app;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.text.style.TypefaceSpan;
public class CustomTypefaceSpan extends TypefaceSpan {
private final Typeface newType;
public CustomTypefaceSpan(String family, Typeface type) {
super(family);
newType = type;
}
@Override
public void updateDrawState(TextPaint ds) {
applyCustomTypeFace(ds, newType);
}
@Override
public void updateMeasureState(TextPaint paint) {
applyCustomTypeFace(paint, newType);
}
private static void applyCustomTypeFace(Paint paint, Typeface tf) {
int oldStyle;
Typeface old = paint.getTypeface();
if (old == null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
}
int fake = oldStyle & ~tf.getStyle();
if ((fake & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fake & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTypeface(tf);
}
}
和DataKinds
的情况:
KindSignatures
如何编写函数,例如{-# LANGUAGE DataKinds, KindSignatures #-}
data Foo = A | B
data GenMe (w :: Foo) = GenMe Int
[| $(generate some code) :: GenMe $(genType someCompileTimeData) |]
genType
提升只是提升保存编译时genType :: Foo -> Q Type
值的变量?我不知道Type Data Constructors使用哪个构造函数
制作数据类型。
有什么想法?谢谢!
答案 0 :(得分:1)
解决此问题的另一种方法是定义promote :: Exp -> Maybe Type
函数,然后在Foo
上使用lift
。
-- | Takes the AST for an expression and tries to produce the corresponding
-- promoted type AST.
promote :: Exp -> Q Type
promote (VarE n) = fail ("Cannot promote variable " ++ show n)
promote (ConE n) = pure (PromotedT n)
promote (LitE l) = LitT <$> promoteLit l
promote (TupE es) = foldl AppT (PromotedTupleT (length es)) <$> (traverse promote es)
promote (ListE es) = foldr (\x xs -> AppT (AppT PromotedConsT x) xs) PromotedNilT <$> (traverse promote es)
promote (ParensE e) = ParensT <$> promote e
promote (AppE e1 e2) = AppT <$> promote e1 <*> promote e2
promote (InfixE (Just e1) e2 (Just e3)) = AppT <$> (AppT <$> promote e2 <*> promote e1) <*> promote e3
promote _ = fail "Either impossible to promote or unimplemented"
-- | Promote an expression literal to a type one
promoteLit :: Lit -> Q TyLit
promoteLit (StringL s) = pure (StrTyLit s)
promoteLit (IntegerL i) = pure (NumTyLit i)
promoteLit _ = fail "Expression literal cannot be promoted"
然后,我认为以下内容应该有效
ghci> :set -XDeriveLift -XDataKinds -XKindSignatures -XTemplateHaskell -XQuasiQuotes
ghci> data Foo = A | B deriving (Lift)
ghci> foo1 = A
ghci> data GenMe (w :: Foo) = GenMe Int
ghci> runQ [| GenMe 1 :: GenMe $(promote =<< lift foo1) |]
SigE (AppE (ConE Ghci5.GenMe) (LitE (IntegerL 1))) (AppT (ConT Ghci5.GenMe) (PromotedT Ghci3.A))