感谢《Real World Haskell》在网上的免费发布,可以白嫖学Haskell这个久闻大名的函数式编程语言了。

本文运行于openSUSE Tumbleweed下,运行相关命令时留意。

安装

Linux下想搞和编程相关的事情非常简单,至少比配置游戏要简单。

sudo zypper in ghc

ghc即Glasgow Haskell Compiler,一个主流的编译器。也支持python式的互动执行(ghci)。笔者运行时该编译器已经是8.0.2版本了。

运行

输入ghci,会进入Haskell的interactive interpreter。大概的运行界面如下:

# zuiho @ zuiho-pc in ~ [Time]
$ ghci
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Prelude>

根据书中的说法,“The word Prelude in the prompt indicates that Prelude, a standard library of useful functions, is loaded and ready to use. When we load other modules or source files, they will show up in the prompt, too.”即prelude是一个基本模块,初始情况会加载它。而如果加载了其它模块,那么会变成这样:

Prelude> :module + Data.Ratio
Prelude Data.Ratio>

可想而知,如果加载了114514个模块,那么长度会比较麻烦(但好处是告诉运行者加载了哪些模块)。这本书里面建议了一个方法,来避免这个可能的情况出现:

Prelude Data.Ratio> :set prompt "ghci> "
ghci>

基本功能

计算器

可以当计算器使用,除法不去尾,^与**作为幂次进行计算(前者后跟整数,后者后跟浮点数)。值得一提的是,支持前缀表达式,只要给操作符加上括号:

ghci> (+) 2 2
4

而Haskell中的“-”是一个一元操作符,也就是说,-3的意思是一个数字3再加上前面的减法操作符。这意味着这样的操作会出现问题:

ghci> 22 + -33

<interactive>:3:1: error:
Precedence parsing error
cannot mix ‘+’ [infixl 6] and prefix `-' [infixl 6] in the same infix expression

想要使用熟悉的负数必须这么用:“6+(-(1/3))”。这样做的原因在于,Haskell内应用函数的方法类似这样:“f 4”。那么如果出现“f -3”就会出现歧义:这个f到底是变量还是函数?这个-3是参数吗?类似的道理,如果输入“2*-3”同样会报错,因为编译器会把*-当作一个参数。这些和负数相关的东西需要我们记住。

布尔值、比较操作符

布尔值(True/False)不能同1与0直接等价,二者相比较会出现错误(相关内容见下报错信息)。逻辑与与逻辑或的操作符号分别为&&与||。Haskell里,逻辑操作符的参数必须为Bool型。
各种比较操作符(comparison operator)返回bool值。Haskell里的不等于是/=,类似≠≠;其逻辑非的操作符是not而不是!。

预设值与赋值

一部分变量是有预设值的,如ππ,是可以直接通过pi来访问的。但是e不是。利用let语句我们可以给变量赋值。

ghci> let e = exp 1

注意,这里的exp是内嵌函数,而Haskell的特色就是调用函数不加括号。

进一步了解

实际上,在上面的探索过程中,至少笔者本人已经会遇到一些报错信息。这个时候可以去浏览网上的帮助文档来解决自己的疑难。Haskell给的报错信息是很有条理的,至少不会一个错爆出来十几个Error和四五十个Note。

列表及其操作

列表类似python的语法([1,2,3]),但是其内部成员类型应当一致。同样,我们可以利用类似pascal的语法来声明一个列表:

ghci> [1..10]
[1,2,3,4,5,6,7,8,9,10]

..表示枚举,它只适用于可枚举的对象,形成一个闭区间。比如说你对”angry”和”excited”枚举是无意义的。
利用这种语法可以写出各种骚序列:

ghci> [1.0,1.25..2.0]
[1.0,1.25,1.5,1.75,2.0]
ghci> [1,4..15]
[1,4,7,10,13]
ghci> [10,9..1]
[10,9,8,7,6,5,4,3,2,1]

给定的第一、第二项决定了公差(对于浮点数,请注意浮点数误差问题)。注意第二种情况,由于13+3=16>15,并没有把15/16给进去。

列表间操作

连接两个列表用++符号。在列表头加入一个元素用:符号。具体的示例见下:

ghci> [] ++ [False,True] ++ [True]
[False,True,True]
ghci> 1:[5,5,1]
[1,5,5,1]

你可以试试[1,5,5]:1会发生什么,反正结果蛮气人的。

字符(串)

双引号规定字符串。接受转义字符。putStrLn输出一字符串。单引号规定字符。实际上,双引号和由单引号构成的列表似乎是等价的:

ghci> let a = ['l', 'o', 't', 's', ' ', 'o', 'f', ' ', 'w', 'o', 'r', 'k']
ghci> a
"lots of work"
ghci> a == "lots of work"
True

这样,适用于列表的操作应当亦适用于字符串。

一个实际的程序

-- file: WC.hs
-- lines beginning with "--" are comments. main = interact wordCount
where wordCount input = show (length (lines input)) ++ "\n"

“–”如所见,两个连杠是注释的标志。将这段程序保存到WC.hs文件中,你想要处理的输入保存到一文件中,然后运行它(runghc WC < I_am_a_input.txt),它会计算输入的内容的行数。这段操作的原理后面会提及。

「Haskell 学习」一 环境与大致了解的更多相关文章

  1. 「Haskell 学习」二 类型和函数(上)

    随着学习的深入,笔记会补充和修订.当然,这个补充修订也许会鸽,但我一定会坚持写完. 这个笔记假定你至少学过C/C++及Python,或与这两种语言类型相同的语言. 类型系统概述 “Haskell’s ...

  2. 「知识学习」二分图的最大匹配、完美匹配和匈牙利算法(HDU-2063)

    定义 如果一个图\((E,V)\)的顶点集\(E\)能够被能够被分成两个不相交的集合\(X,Y\),且每一条边都恰连接\(X,Y\)中的各一个顶点,那么这个图就是一个二分图. 容易得知,它就是不含有奇 ...

  3. NLP领域的ImageNet时代到来:词嵌入「已死」,语言模型当立

    http://3g.163.com/all/article/DM995J240511AQHO.html 选自the Gradient 作者:Sebastian Ruder 机器之心编译 计算机视觉领域 ...

  4. 从0开始学习 GITHUB 系列之「GIT 速成」【转】

    本文转载自:http://stormzhang.com/github/2016/05/30/learn-github-from-zero3/ 版权声明:本文为 stormzhang 原创文章,可以随意 ...

  5. 从0开始学习 GITHUB 系列之「加入 GITHUB」【转】

    本文转载自:http://stormzhang.com/github/2016/05/26/learn-github-from-zero2/ 版权声明:本文为 stormzhang 原创文章,可以随意 ...

  6. 「C语言」Windows+EclipseCDT下的C语言开发环境准备

    之前写过一篇 「C语言」在Windows平台搭建C语言开发环境的多种方式 ,讨论了如何在Windows下用DEV C++.EclipseCDT.VisualStudio.Sublime Test.Cl ...

  7. DDD 实战记录——实现「借鉴学习计划」

    「借鉴学习计划」的核心是:复制一份别人的学习计划到自己的计划中,并同步推送学习任务给自己,并且每个操作都要发送通知给对方. 它们的类图如下: 它们的关系是一对多: // Schedule entity ...

  8. 有些lambda表达式就可以体现出编程中「Context(上下文)」环境

    编程中什么是「Context(上下文)」?   每一段程序都有很多外部变量.只有像Add这种简单的函数才是没有外部变量的.一旦你的一段程序有了外部变量,这段程序就不完整,不能独立运行.你为了使他们运行 ...

  9. Note -「Lagrange 插值」学习笔记

    目录 问题引入 思考 Lagrange 插值法 插值过程 代码实现 实际应用 「洛谷 P4781」「模板」拉格朗日插值 「洛谷 P4463」calc 题意简述 数据规模 Solution Step 1 ...

随机推荐

  1. [19/03/23-星期六] 容器_ 泛型Generics

    一.概念 生活中的容器不难理解,是用来容纳物体的,程序中的“容器”也有类似的功能,就是用来容纳和管理数据. 数组就是一种容器,可以在其中放置对象或基本类型数据. ---优势:是一种简单的线性序列,可以 ...

  2. python常见异常及解决方法

    异常1: ValueError: unsupported hash type sha224 ERROR:root:code for hash sha256 was not found. Traceba ...

  3. Git使用(一)

    声明: 第一次使用git,只能保证我的方法可以用,肯定不是最简最好的.以后需要用到更多的用法的时候再来这里更新. 说实话,记下来主要是因为自己记性不好,各种配置记不住,都是当备忘录用的,(囧囧囧囧囧) ...

  4. JavaEE权限管理系统的搭建(四)--------使用拦截器实现登录认证和apache shiro密码加密

    RBAC 基于角色的权限访问控制(Role-Based Access Control)在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限.这就极大地简化了权限的管理.在一个 ...

  5. 开始重学java【门头沟2017年12月6日】

    现在从struts2开始重新学习java, 想找个人一起学习java/php都可以. 学习时间大概是两个月,就是年前这段时间. 下一个阶段就是做项目进行练习.(时间为:一个月时间) 不管是学习java ...

  6. mui 的多图片上传

    pickHead(){ var _this = this; plus.gallery.pick(function(path){ _this.headImage=path; var files = [{ ...

  7. Unity 游戏框架搭建 (九) 减少加班利器-QConsole

    为毛要实现这个工具? 在我小时候,每当游戏在真机运行时,我们看到的日志是这样的. 没高亮啊,还有乱七八糟的堆栈信息,好干扰日志查看,好影响心情. 还有就是必须始终连着usb线啊,我想要想躺着测试... ...

  8. linux下ssh/sftp配置和权限设置

    基于 ssh 的 sftp 服务相比 ftp 有更好的安全性(非明文帐号密码传输)和方便的权限管理(限制用户的活动目录). 1.开通 sftp 帐号,使用户只能 sftp 操作文件, 而不能 ssh ...

  9. 使用DOM对表格进行增删

    ---恢复内容开始--- 声明本文旨在练习dom 其中可以链接数据 或者使用ajax 实现的我全用的dom因为我在学dom. 一. 表格构建 <section id="section_ ...

  10. linux下进程的最大线程数、进程最大数、进程打开的文件数

    linux下进程的最大线程数.进程最大数.进程打开的文件数   ===========最大线程数============== linux 系统中单个进程的最大线程数有其最大的限制 PTHREAD_TH ...