Chinaunix首页 | 论坛 | 博客
  • 博客访问: 467397
  • 博文数量: 55
  • 博客积分: 2603
  • 博客等级: 少校
  • 技术积分: 750
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-31 02:30
文章分类

全部博文(55)

文章存档

2011年(1)

2010年(22)

2009年(17)

2008年(15)

我的朋友

分类:

2008-12-07 16:51:00

前一章其实标题本来是"编译与运行"。但是这两步反而难度不高,看了教程就很容易能明白,所以我没有讨论它。
上一章里重点介绍了开发工具,因为Haskell的语法决定,我们需要一个顺手的工具。
还重点介绍了Monad,主要是从我等下里巴人的角度解释一下怎么用它。
对于一个完全的新手,其实还应该学习一些关于Haskell基本数据结构和函数定义的知识,不过这方面的东西最好找专门的Haskell语言教程。

这一章,会继续练习Monad的使用。我们还会见到一些来自GHC标准库的强大武器。

这次我们 import 进来一个新的库

1 import Text.ParserCombinators.Parsec hiding (spaces)

Parsec库是Haskell中专门的解释器工具库。hiding关键字指出,我们导入这个库时,把 spaces 函数排除在外--因为我们随后要自己实现一个不同的逻辑。

Haskell语言:

1 symbol :: Parser Char
2 symbol = oneOf "!#$%&|*+-/:<=>?@^_~"


上面是类型声明,也就是说给oneOf函数传这一串符号进去,它返回一个解释器类型。其接收代码文本,针对oneOf传入的符号串进行处理。类似oneOf的这些解释器Monad生成工具,在Parsec库里还有一些其它的解析工具,后面我们会用到一些。

OK,这个解释器(其实是个解释器零件)我们怎么使用它呢?现在我们写一个解析表达式的工具:


Haskell语言:

1 readExpr :: String -> String
2 readExpr input = case parse symbol "lisp" input of
3     Left err -> "No match: " ++ show err
4     Right val -> "Found value"


这个用法很简单,利用 Parsec 库的 parse,我们把定义好的 symbol 传给 parse ("lisp" 作为注册进来的 symbol 的命名),然后接收一个字符串,parse会返回一个 data ,其中 Left 是表示错误信息,err中有具体内容,Right val则是匹配正确后的结果,这里我们先不管它返回了什么,输出一个"Found value"。

这段程序可以看出,symbol 的作用比较简单,只要字符串里有任一个匹配oneOf的字符,解析器会把它做为一个词素提出来。而parse就处理这个解析结果。



这样,很简单的接收命令行参数然后传出解析结果。!!是haskell的列表索引操作符。也就是说,它只处理args的第一个元素。
编译以后执行试试吧,你会看到,它校验你输入的文本中,第一个字符是否在symbol注册的符号中。并返回相应的值。
解释器还很简单,但是后面我们会慢慢完善它。

这一章的重点,在于学会如何组合多个函数或Monad。具体的原理和定义,推荐一份已经被汉化出来的教程:函数式编程另类指南,其中的currying和Continuations知识,与我们在这里使用的组合技术相关。

事实上,如果那东西把你搞糊涂了,倒不如当那些名词和定理不存在,我们继续写程序吧XD。

今天的代码:


Haskell语言:

01 module Main where
02
03 import System.Environment
04 import Text.ParserCombinators.Parsec hiding (spaces)
05
06 symbol :: Parser Char
07 symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
08
09 readExpr :: String -> String
10 readExpr input = case parse symbol "lisp" input of
11                    Left err -> "No match: " ++ show err
12                    Right val -> "Found value"
13
14 main :: IO ()
15 main = do args <- getArgs
16           putStrLn (readExpr (args !! 0))
阅读(725) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~