haskell - 我如何在 Haskell 中显示派生树?

标签 haskell tree functional-programming semantics algebraic-data-types

我正在做一个练习,构建 while 语言的派生树。我的 while 语言的实现是由代数数据类型组成的,例如“Aexp”(算术表达式)“Bexp”( bool 表达式)和“Stm”(语句):

type  Var   =  String
data  Aexp  =  N Integer
        |  V Var
        |  Add Aexp Aexp
        |  Mult Aexp Aexp
        |  Sub Aexp Aexp
        deriving (Show, Eq)

data  Bexp  =  TRUE
        |  FALSE
        |  Eq Aexp Aexp
        |  Le Aexp Aexp
        |  Neg Bexp
        |  And Bexp Bexp
        deriving (Show, Eq)

data  Stm   =  Ass Var Aexp
        |  Skip
        |  Comp Stm Stm
        |  If Bexp Stm Stm
        |  While Bexp Stm
        |  Repeat Stm Bexp
        deriving Show

在这些代数数据类型之后,我创建了更多代数数据类型来表示 while 语言程序的派生树

type  State  =  Var -> Z

data Config = Inter Stm State  -- <S, s>
        | Final State      -- s

data Transition = Config :-->:  State

data DerivTree = AssNS     Transition
           | SkipNS    Transition
           | CompNS    Transition DerivTree DerivTree
           | IfTTNS    Transition DerivTree
           | IfFFNS    Transition DerivTree
           | WhileTTNS Transition DerivTree DerivTree
           | WhileFFNS Transition
           | RepeatTTNS Transition 
           | RepeatFFNS Transition DerivTree DerivTree

如何展示这种推导树?

<z:=x, s> -> s'    <x:=,s1> -> s''
----------------------------------
    <z:=x; x:=y,s> -> s''             <y:=z,s''> -> s'''
    ------------------------------------------------------
            <z:=x; x:=y; y:=z, s> -> s'''

每个构造函数的预期值如下所示:

enter image description here

最佳答案

这是一个使用 boxes 的简单示例包来生成类似派生树的东西。您应该能够轻松地使其适应您的需求 - 通过生成 Tree String,或者使用 pp 中的想法来生成 直接从派生树中框出。 (我选择在这里使用 Tree String 而不是您的类型,主要是为了避免必须弄清楚具有大量构造函数的数据类型的所有 pretty-print 细节。)

import Data.Tree
import Text.PrettyPrint.Boxes

pp :: Tree String -> Box
pp (Node here []      ) = text here
pp (Node here children) = vcat center1 [premises, separator, conclusion]
    where
    premises   = hsep 4 bottom (map pp children)
    conclusion = text here
    width      = max (cols premises) (cols conclusion)
    separator  = text (replicate width '-')

sampleTree :: Tree String
sampleTree = Node "<z:=x; x:=y; y:=z, s> -> s'''"
    [Node "<z:=x; x:=y,s> -> s''"
        [Node "<z:=x, s> -> s'" []
        ,Node "<x:=,s1> -> s''" []
        ]
    ,Node "<y:=z, s''> -> s'''" []
    ]

这是在 ghci 中运行的示例:

*Main> printBox (pp sampleTree)
<z:=x, s> -> s'    <x:=,s1> -> s''                       
----------------------------------                       
      <z:=x; x:=y,s> -> s''           <y:=z, s''> -> s'''
---------------------------------------------------------
              <z:=x; x:=y; y:=z, s> -> s'''              

关于haskell - 我如何在 Haskell 中显示派生树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33741937/

相关文章:

javascript - 如何使用 d3.js 展开可折叠树上的特定节点?

algorithm - 在无根树中查找多个 LCA

Haskell:Data.Set `notMember` 比 `notElem` 慢?

haskell - 使用 Control.Lens 中的多个 Getter 调用函数的干净方法是什么?

haskell - 类型签名需要库未导出的类型

java - 打印树的最小和路径

functional-programming - 在 Scheme 中定义一个宏来创建花哨的子列表

javascript - 是否可以绑定(bind)一个javascript函数,使其本地上下文与 'this'相同?

python - Python 中的函数式中缀实现

haskell - 封闭类型族和奇怪的函数类型