用前缀表示法重写Haskell表达式

时间:2016-03-18 18:47:25

标签: haskell

我想实现一个程序来接受任何Haskell表达式并使用前缀表示法重写它。

我希望GHC本身会转储一些有用的信息(比如解析后添加的括号),但不幸的是,情况似乎并非如此。

$ ghc Example.hs -fforce-recomp -ddump-tc
[1 of 1] Compiling Example          ( Example.hs, Example.o )
TYPE SIGNATURES
  f :: Maybe ()
TYPE CONSTRUCTORS
COERCION AXIOMS
Dependent modules: []
Dependent packages: [base-4.8.1.0, ghc-prim-0.4.0.0,
                     integer-gmp-1.0.0.0]

==================== Typechecker ====================
AbsBinds [] []
  {Exports: [f <= f_alA
               <>]
   Exported types: f :: Maybe ()
                   [LclId, Str=DmdType]
   Binds: f_alA = ($) const (GHC.Base.Just) "Foo" GHC.Tuple.()}

哪种现有API最适合此任务?

1 个答案:

答案 0 :(得分:3)

  

哪种现有API最适合此任务?

使用Template Haskell和一个包th-desugar来模糊模板Haskell。这个想法很简单:将表达式包装在准引用中,将其作为模板haskell,然后再将其渲染为haskell代码。

我在这里重复使用代码以获得其他答案,所以它可能有点混乱:

{-# LANGUAGE DeriveGeneric   #-}
{-# LANGUAGE QuasiQuotes     #-}
{-# LANGUAGE TemplateHaskell #-}

import           Control.Monad
import           Generics.Deriving.Monoid
import           GHC.Generics
import           Language.Haskell.TH.Desugar

data T = MkT {str :: String, str' :: String}
  deriving (Generic, Show)

main = $([| print $ MkT "a" "b" `mappend` MkT "c" "d" |] >>= dsExp >>= return . expToTH)

instance Monoid T where
  mempty = memptydefault
  mappend = mappenddefault

通过-ddump-splices ghc将转储*.dump-splices文件,显示haskell对源代码所执行的模板:

app\Main.hs:12:10-87: Splicing expression
    [| print $ MkT "a" "b" `mappend` MkT "c" "d" |] >>= dsExp
    >>= return . expToTH
  ======>
    ($) print (mappend (MkT "a" "b") (MkT "c" "d"))