1. 准备环境
首先下载Haskell Platform,它包含了GHC,Cabal,还有其他的一些工具。
Mac OS X下载完后是一个pkg文件,例如,Haskell Platform 8.2.2 Full 64bit-signed.pkg
,
双击安装即可。
2. 新建工程
使用cabal
命令行工具,初始化工程,
$ mkdir my-tree-diff # 新建工程目录
$ cd my-tree-diff # 进入目录
$ cabal init # 初始化项目
然后就有一些提示,以填写与工程相关的配置选项,
例如,package-name,package version,license,author name,maintainer email,等等。
一般使用默认值即可,唯一需要手动输入选项的是,
> What does the package build:
1) Library
2) Executable
Your choice? 2 # 这里我们选2,工程会生成一个可执行文件
填写完成后,cabal
会自动生成一些文件,
my-tree-diff
├── ChangeLog.md
├── LICENSE
├── Main.hs
├── Setup.hs
└── my-tree-diff.cabal
3. 编译 & 运行
直接在工程目录下,执行cabal run
,就会自动编译并执行,
$ cabal run
Resolving dependencies...
Configuring my-tree-diff-0.1.0.0...
Preprocessing executable 'my-tree-diff' for my-tree-diff-0.1.0.0..
Building executable 'my-tree-diff' for my-tree-diff-0.1.0.0..
[1 of 1] Compiling Main ( Main.hs, dist/build/my-tree-diff/my-tree-diff-tmp/Main.o )
Linking dist/build/my-tree-diff/my-tree-diff ...
Running my-tree-diff...
Hello, Haskell!
其中,Hello, Haskell!
是Main.hs
中输入的结果,
module Main where
main :: IO ()
main = putStrLn "Hello, Haskell!"
注:
如果只编译,可以执行cabal build
,
$ cabal build
Preprocessing executable 'my-tree-diff' for my-tree-diff-0.1.0.0..
Building executable 'my-tree-diff' for my-tree-diff-0.1.0.0..
4. 工程依赖
使用cabal
创建的工程,依赖的Hackage包,需要在my-tree-diff.cabal
文件中配置,
在该文件中,我们可以找到,build-depends: base >=4.10 && <4.11
,
它表示默认依赖了base
包。
我们修改build-depends
字段的值,为之添加以下包,
他们是本例展示tree-diff使用方法所必须的,
build-depends:
base >=4.10 && <4.11,
tree-diff,
containers,
pretty
其中base
,tree-diff
,containers
,pretty
为Hackage中的包名,
各依赖通过逗号来隔开,也可以省略版本号。
5. 修改Main.hs文件
module Main where
import Data.Tree -- 隶属于containers包
import Text.PrettyPrint -- 隶属于pretty包
import Data.TreeDiff -- 隶属于tree-diff包
tree1 :: Tree Char
tree1 = Node 'a' [
return 'b',
Node 'c' [
return 'd',
return 'e'
],
return 'f'
]
tree2 :: Tree Char
tree2 = Node 'a' [
return 'b',
Node 'c' [
return 'd',
return 'e'
],
return 'g'
]
main :: IO ()
main = putStrLn $ render $ prettyEditExpr $ ediff tree1 tree2
其中,ediff,prettyEditExpr,render的类型如下,
-- tree-diff包,Data.TreeDiff.Class模块中
ediff :: ToExpr a => a -> a -> Edit EditExpr
-- tree包,Data.TreeDiff.Pretty模块中
prettyEditExpr :: Edit EditExpr -> Doc
-- pretty包,Text.PrettyPrint模块中
render :: Doc -> String
此外,return的类型如下,
-- containers包,Data.Tree模块中
return :: a -> Tree a
6. 执行结果
$ cabal run
Preprocessing executable 'my-tree-diff' for my-tree-diff-0.1.0.0..
Building executable 'my-tree-diff' for my-tree-diff-0.1.0.0..
[1 of 1] Compiling Main ( Main.hs, dist/build/my-tree-diff/my-tree-diff-tmp/Main.o )
Linking dist/build/my-tree-diff/my-tree-diff ...
Running my-tree-diff...
Node
'a'
[Node 'b' [],
Node 'c' [Node 'd' [], Node 'e' []],
Node -'f' +'g' []]
参考
Haskell: Downloads
The Haskell Cabal
Hackage: tree-diff - Data.TreeDiff.Class - ediff
Hackage: tree-diff - Data.TreeDiff.Pretty - prettyEditExpr
Hackage: pretty - Text.PrettyPrint - render
Hackage: containers - Data.Tree - return