`
tangtong
  • 浏览: 62914 次
  • 来自: ...
社区版块
存档分类
最新评论

Write Yourself a Scheme in 48 Hours(2)

阅读更多


2. 第一步

首先,你需要安装 GHC 。在 Linux 环境,它常常被预安装了或者能够通过 apt-get 或者 yum 命令获得。它也可以从 http://www.haskell.org/ghc/ 下载。二进制包大概是最容易的,除非你真的知道你在做什么。 GHC 应该像其他的软件包一样下载和安装。这个教程在 Linux 下面完成,但是如果你知道如何使用 DOS 命令行所有的东西应该能够在 Windows 环境下工作。

有一个非常棒的 Emacs mode 提供给 UNIX (或者 Windows Emacs) 用户,包括语法高亮和自动缩进。 Windows 用户能够使用记事本或者其他文本编辑器; Haskell 语法对记事本相当友好,尽管你需要对缩进小心处理。

 

现在,是时候写你的第一个 Haskell 程序。这个程序将通过命令行读入一个名字然后输出一个问候。建立一个文件一 ".hs” 结尾并输入下列代码:

module Main where
import System.Environment

main :: IO ()
main = do args <- getArgs
      putStrLn ("Hello, " ++ args !! 0)
 

让我们看看这段代码。最开始的两行指定了我们将创造一个以 Main 命名的模块,这个模块将引入 (import) System 模块。每一个 Haskell 程序从一个 Main 模块的 main 函数开始。那个模块可以导入其它模块,但是必须把它提供给编译器生成一个可执行文件。 Haskell 是区分大小写的:模块的名字永远是大写开头的,生命永远是非大写开头的。

 

main :: IO () 这一行是一个类型声明: "main” 函数有 "IO ()” 类型。类型声明在 Haskell 里面是可选的:编译器能够自动的识别他们,当你的声明和编译器自动识别发生冲突的时候它会报错。在这个教程里,为了更清晰,所有的类型声明我都显式声明了。当你在家里跟随这个教程的时候,你可能想要忽略这些类型声明,因为在我们编写这个程序的时候不需要改动它们。

 

IO 类型是 monad 的一个实例, monad 是一个吓人的名词不过含义却很简单。简单说, monad 是一个声明“有一些附加信息,大多数函数都不要对这些附加信息担心”的方法。在这个例子里,“附加信息”是这个函数执行了 IO 的情况,而它的基本值是无,用 "()” 表示。 Monadic 值常被称作 "actions” ,因为这是最容易的方法来思考 IO monad 是一系列的动作,而这些动作可能会影响外界世界。

 

Haskell 是一个声明式语言:除了告诉计算机一系列需要执行的指令,你还告诉它如何执行这些函数的定义。这些定义将各种动作和函数组合在一起。编译器识别出把所有定义放在一起的执行路径。( bad

 

要写一个这样的定义,你需要建立一个等式。等式的左边定义一个名字,可能会有一个或者更多的会与变量帮定的 patterns (后面解释 ) 。等式的右边定义 (TODO) <!-- @page { margin: 0.79in } P { margin-bottom: 0.08in } A:link { so-language: zxx } -->

了一些其它告诉计算机当碰到这些名字应该干什么的定义。这些等式表现得就像一般的代数等式:你总是可以在程序里用右边的部分替代左式,这种替换不会改变计算值。这种行为被称作 "referential transparency" ,这种性质使得 Haskell 代码比其它的语言容易懂得多。

那我们又要如何定义 main 函数呢?我们知道必须有一个 IO () 动作,而且我们想要它读入命令行参数,然后答应一些输出。这里有两种方法创建一个 IO 动作:

  1. return 函数提升 (lift) 一个普通值进入 IO monad

  2. 把两个 IO 动作连接起来。

因为我们要做两件事情,我们将使用第二种方法。内建动作 getArgs 读入所有命令行参数并把它们存入一个字符串列表。内建函数 putStrLn 将一个字符串输出到终端。

我们使用 do-block 连接它们。 do-block 包括很多行,所有的行按照第一个非空白字符在 do 后面排列。每一行能有下面两种形式之一:

  1. name <- action

  2. action

第一种形式将 action 的结果和 name 绑定。例如,如果有一个动作的类型是 IO [String]( 一个 IO 动作会返回一个字符串列表,就像 getArgs) ,然后 "name” 就会和这个返回的字符串列表绑定。爹人中形式会执行这个动作,把上面的行用 >> 操作符连结在一起。这个操作符在不同的 monad 里面有不同的语义:如果在 IO monad 中,他会连续执行所有的动作,执行无论什么会产生外部副作用的操作。因为这个连接符的语义依赖你使用的 monad ,所以你不能在同一个 do-block 里把不同 monad 类型的操作连在一起。

当然,这些动作可能自己就是函数的结果或者复杂的表达式。在这个例子里,我们首先取出参数列表中的 0 元素 (args !! 0) ,把他连接到字符串 "Hello, “ 的后面 (“Hello, “ ++) ,最后把结果传给 putStrLn 。字符串在 Haskell 是一串字符,所以在字符串上你可以使用任何列表函数和操作符。一个标准操作符和它们的优先权如下表:

(table omited)

编译和运行这个程序,你可以这么做:

 

debian:/home/jdtang/haskell_tutorial/code# ghc -o hello_you listing2.hs
debian:/home/jdtang/haskell_tutorial/code# ./hello_you Jonathan
Hello, Jonathan

  -o 选项指定了你想创造的可执行程序的名字,然后你指定 Haskell 源程序名字。

 

习题:

1.修改程序,让它从命令行读入两个参数,然后输入一个包括这两个参数的信息。

2.修改程序,让它对输入的两个参数执行一个简单的算术操作然后把结果输出。你可以使用 read 来转换字符串成数字,和 show 转换一个数字回字符串。再用不同的操作符试试。

3.getLine 是一个 IO 动作,它能从终端读入一行然后把结果作为字符串返回。修改程序让它提示需要一个名字,然后读入名字,最后输出它。而不是从命令行读入。

 

 

 

分享到:
评论

相关推荐

    Write Yourself a Scheme in 48 Hours

    Write a Scheme interpreter in Haskell step by step.

    Teach Yourself Scheme in Fixnum Days

    《Teach Yourself Scheme in Fixnum Days》是一本关于Scheme编程语言的自学教程,本书内容涵盖了从基础到高级的多个知识点,致力于让读者在有限的天数内掌握Scheme编程。在进行知识点梳理之前,我们先对文档内容进行...

    Teach.Yourself.Scheme.in.Fixnum.Days

    《Teach Yourself Scheme in Fixnum Days》是一本由Dorai Sitaram编写的经典书籍,旨在教授读者如何在有限的时间内掌握Scheme编程语言。Scheme是Lisp家族的一种方言,以其简洁性和灵活性而著称,是计算机科学教育和...

    Mit.Press-Teach.Yourself.Scheme.pdf (英文)

    《Teach Yourself Scheme in Fixnum Days》是一本详尽的教程,旨在帮助读者在有限的时间内掌握Scheme语言的基础及进阶知识。此书由Dorai Sitaram撰写,并且在网络上部分中文翻译已经存在(参考链接:...

    Programming In Scheme

    Chapters are organized as a series of groups, or "layers," each of which advances the reader to a new level in Scheme. The first layer (chapters 2-7) introduces Scheme procedures - how to define, use,...

    write-yourself-a-scheme-no-compiler-errors:与“Write Yourself a Scheme”相关的源代码简单地修改为使用最近的 ghcs 编译

    编写自己的方案无编译器错误“为自己编写一个计划”教程,其中包含一些微不足道的修改。 涉及 Read 类型类的错误非常令人分心; 我已经在listing7.hs、listing8.hs 等中留下了关于重叠模式匹配的警告,因为它只是一...

    scheme语言学习资料集合

    scheme语言相关的学习资料: guide_racket_scheme.pdf Lisp之根源.pdf Racket图文教程.pdf scheme-primer.pdf ...The_Little_Schemer.pdf ...Write_Yourself_a_Scheme_in_48_Hours.pdf The+Seasoned+Schemer.pdf

    write-yourself-a-scheme:48小时内为自己编写计划的游乐场

    标题 "write-yourself-a-scheme:48小时内为自己编写计划的游乐场" 指的是一项挑战,旨在引导参与者在48小时内学习并实现Scheme语言的一个简易解释器。这是一个编程项目,通过它,开发者可以深入理解编程语言的内部...

    A Preprocessing Scheme for High-Cardinality Categorical Attributes

    "A Preprocessing Scheme for High-Cardinality Categorical Attributes"这个主题探讨的就是如何有效地处理这类问题。 一、高基数类别变量的挑战 1. 维度灾难:高基数会导致数据的维度增加,这可能会引起过拟合,...

    (How to Write a (Lisp) Interpreter (in Python))中文版(包括上下篇)

    (How to Write a (Lisp) Interpreter (in Python))和(An ((Even Better) Lisp) Interpreter (in Python))的翻译,对解释器实现原理和函数式编程敢兴趣的可以下载看看!

    A novel color image watermarking scheme in nonsampled contourlet-domain

    ### 一种非采样轮廓域中的新型彩色图像水印方案 #### 概述 本文介绍了一种基于非采样轮廓变换(NSCT)和支持向量回归(SVR)技术的新型彩色图像水印算法。该算法针对几何畸变攻击具有良好的抵抗能力,能够在保持...

    Dybvig. The Scheme Programming Language

    This thoroughly updated edition of The Scheme Programming Language provides an introduction to Scheme and a definitive reference for standard Scheme, presented in a clear and concise manner....

    scheme语言的解释器scheme48

    scheme语言的解释器scheme48

    scheme_in_forth.tar_in_scheme_forth_源码

    标题 "scheme_in_forth.tar_in_scheme_forth_源码" 提供的信息表明,这是一个关于用Forth语言实现Scheme解释器的项目。Forth是一种结构简单、效率高的编程语言,而Scheme是Lisp家族的一种方言,以其简洁的语法和强大...

    APK Signature Scheme v2验证工具

    APK Signature Scheme v2验证工具

    A_Tour_of_Scheme_in_Gambit

    《A Tour of Scheme in Gambit》是一份详尽的指南,旨在介绍如何在Gambit-C解释器中使用Scheme语言进行编程。这份文档由Mikael More撰写,并且允许免费无限传播,前提是保留原有的版权信息。文档提供了PDF、HTML和...

    A_Reliale A-MSDU Frame Aggregation scheme in 802.11n

    针对802.11n的聚合机制,提出一种解决方法:In this paper, we proposed an A-MSDU frame aggregation with sub-frame integrity check and retransmission at the MSDU level without altering the original MAC ...

Global site tag (gtag.js) - Google Analytics