斯坦福公开课《编程范式》中介绍了Scheme(但是不仅仅是Scheme,它只是作为函数式语言的代表),最后一课介绍了Haskell。。。

“Hello World!”是学习一门语言的魔咒 :)

ghc windows上面的winghci

 
这是一个解释器环境,和python的差不多
 
在提示符后Prelude>后面输入
 
"Hello World"
 
解释器返回 "Hello World",哦耶...
 
当然,你可以输入一些你能想到的功能试试,1 + 1、7/2 ...
 
但是试试 5 mod 3 ... 额...
 
别忘了,童鞋们,这个是函数式语言,其构成可以写成:函数名 参数列表,函数的返回值才是你输出的值(之所以允许 1 + 1, 只是语法糖而已)
 
比如:1+1,应该写成 (+) 1 1, (+) 的括号不能少...因为+这个符号不是一个合法的函数命名)
 
其意义是,调用了一个叫“+”的函数,传入了两个参数,分别是1,1, 函数执行之后,返回的结果为2
 
所以,上面的5 mod 3 应该是 mod 5 3,返回2...
 
来看看list,[1, 2, 3, 4, 5]就是一个list,或者[1, 2..20]也是,类似于ptyhon的range(start,stop,[step]),如:
range(1,21)返回1-20.

*Main> [1,2..20]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
*Main> [1..20]
[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

你还可以[1.2, 1.6..2.1]、[1.0,0.9..0.0]...

*Main> [1.2,1.6..2.1]
[1.2,1.6,2.0]

 
当然,目前这个只能线性的,假如你想输出2, 4, 8, 16, 32...,这个就不能简单搞定了...(其实也很简单...用一下map和lambda就行)
 
list的一些常用操作:
 
length [1, 2, 3, 4] 得到 4
take 2 [1, 2, 3, 4] 得到 [1, 2]
drop 2 [1, 2, 3, 4] 得到 [3, 4]
head [1, 2, 3, 4] 得到 1
tail [1, 2, 3, 4] 得到 [2, 3, 4]
[1, 2, 3, 4] !! 2 得到 3 (这个是下标操作)
 
来看看函数, 新建个文件,比如:helloworld.hs,然后输入:
 
hello = "Hello World!"
 
在GHCi中File -> Load或者使用命令:load "文件名",载入文件
 
然后在提示符输入:hello,得到结果Hello World
 
来写个1加到N的函数
 
sumToN n = sum [1..n]
 
函数名是sumToN,接收一个参数n,使用内置函数sum,然后构造一个从1到n的列表,作为sum的参数
 
如果你好奇sum如何实现,一种简单的实现可以为:
 
sum xs = (+) (head xs) (sum (tail xs))
 
你会发现,原来的循环结构被递归取代,同样会发现,与其想象每一小步操作如何运作(命令式),不如想想你要计算的结果是如何“定义”的(函数式)
 
来一些有if...then...else的吧
 
isSorted,用来判断一个list是否是升序的(暂且这样,后面可以传入比较函数,泛化这个函数)
 
假如传入的参数是 [](空list)或者只有一个元素,那么返回True
 
可以写成
isSorted [] = True
isSorted (x:[]) = True(参数(x:xs)的意义是:假设传入list ns,x是head ns,xs是tail ns) 
 
这个类似于编译原理里面的产生式,在Haskell中被称为模式匹配...意思就是拿参数跟所有的函数签名进行匹配(当然是我所说的只拿函数参数匹配的前提是函数名我确认是isSorted了),顺序是从上到下
 
说好的if...else来了
完整的为:
isSorted [] = True
isSorted (x:[]) = True
isSorted n = if (head n > (n !! 1)) then False
else isSorted (tail n)
 
其实代码就是再定义什么是Sorted
1. 如果列表为空,是sorted
2. 如果列表只有一个元素,是sorted
3. 如果第一个元素比第二个元素大,那么不是sorted,否则sorted依赖于剩下的元素是否sorted
 
再搞一个half函数,功能就是将一个list分成两半,首先搞一个这样的:
 
half :: [b] -> [[b]]
half [] = [[]]
half x | (/=) (mod (length x) 2) 0 = [[]]
| otherwise = (take n x) : (drop n x) : []
where {
n = div (length x) 2
}
第一句,::是定义了这个函数的签名...即输入一个list,返回一个list的list...,这一句不是必须的,因为强大的Haskell可以帮助你推断类型...(这个好多书都放到前面讲,我觉得放到后面说比较合适,因为个人觉得一开始跟少人关心Haskell的类型系统,起码我是这样的)
第二句为空判断,之前已经搞过了
第三句“=”前面的部分是匹配条件
 
(/=) (mod (length x) 2) 0 = [[]]("/="意思是不等于...相当于 != 或者 <>)
的意思是,如果x的长度不为偶数,则返回[[]]
 
otherwise是除了上述条件外,其它的情况
(take n x) : (drop n x) : []
(:) 是个函数...其实应该写成 (:) (take n x) ((:) (drop n x) [])
其作用是,将一个元素加入到一个list的中,比如:(:) 1 [2, 3, 4]得到[1, 2, 3, 4]
 
这里是将两个list合并为一个list(list)中...
 
关于n,其实简化之前应该是:(take (div (length x) 2) x) : (drop (div (length x) 2) x) : []
 
由于同样的式子计算两遍有些可惜,而且不利于表达“定义”,所以,使用了where,在其中定义了n
 
切记,where不应该当做定义变量来使用,而且当做存储递归结果,加速计算来使用
 
在递归式中,有些递归结果在前面的递归中已经计算过,有些计算量很大,则可以使用where在缓冲,加速计算
 
上述half只是为了使用 “|” 操作符来区分一下匹配过程,其实也可以支持list长度为奇数的情况...
 
half :: [b] -> [[b]]
half [] = [[]]
half x = (take n x) : (drop n x) : []
where {
n = div (length x) 2
}
 
先到这吧,后面还有挺多东西的...
 
其实语法不是关键,关键是将编程的思考模式转换到函数式上...
 
大家可以使用上面的只是写个排序...当然,你会发现一些问题...或者说,你无意间发现了函数式的一些特性...

转自:http://emavaj.blog.163.com/blog/static/1332805572013741013704/

haskell入门的更多相关文章

  1. Hashkell 第一篇

    心情极差.................. 无事可做,其实是没心情去做事情,只好又翻起了haskell入门 记下几点,以备查询: 1. 函数名首字符是不可以大写的, 而且名称中可以有单引号,这也是合 ...

  2. Haskell 函数式编程快速入门【草】

    什么是函数式编程 用常规编程语言中的函数指针.委托和Lambda表达式等概念来帮助理解(其实函数式编程就是Lambda演算延伸而来的编程范式). 函数式编程中函数可以被非常容易的定义和传递. Hask ...

  3. Haskell 趣学指南 入门笔记(二)

    显示类型声明,Haskell是不用定义类型的原因,很像python 想要确定某个表达式的类型 *Main> :t 'a' 'a' :: Char *Main> :t True True : ...

  4. Haskell 几乎无疼痛入门指南

    当他重装Linux 机会虚拟机,安装 haskell 录制的过程中有什么.的方式来帮助那些谁在徘徊haskell进入外读者. 基本概念: Haskell : 是一门通用函数式语言.差点儿能够进行不论什 ...

  5. haskell简明入门(一)

    本文的主要内容参考自<Haskell趣学指南> 1. What is Haskell?     以下内容引用自Haskell官网: Haskell是一个先进的,纯粹的函数式编程语言.一个典 ...

  6. Thrift入门及Java实例演示<转载备用>

    Thrift入门及Java实例演示 作者: Michael 日期: 年 月 日 •概述 •下载配置 •基本概念 .数据类型 .服务端编码基本步骤 .客户端编码基本步骤 .数据传输协议 •实例演示(ja ...

  7. Markdown入门基础

    // Markdown入门基础 最近准备开始强迫自己写博文,以治疗严重的拖延症,再不治疗就“病入骨髓,司命之所属,无奈何”了啊.正所谓“工欲善其事,必先利其器”,于是乎在写博文前,博主特地研究了下博文 ...

  8. Git版本控制软件结合GitHub从入门到精通常用命令学习手册(转)

    简要参考:http://www.tuicool.com/articles/mEvaq2 http://gitref.org/zh/index.html GIT 学习手册简介 本站为 Git 学习参考手 ...

  9. Haskell 与范畴论

    说到 Haskell,这真是一门逼格极高的编程语言,一般初学者如果没有相关函数式编程的经验,入门直接接触那些稀奇古怪的概念,简直要跪下.现在回想起来,隐隐觉得初学者所拥有的命令式编程语言(impera ...

随机推荐

  1. 字体图标 icon font

    Icon font icon font 指的是用字体文件代替图片文件,来展示图标.特殊字体等元素的方法. 应用场景: iconfont的优缺点 大小能够自由地变化 颜色能够自由地改动 加入阴影效果 * ...

  2. 怎样使用 iOS 7 的 AVSpeechSynthesizer 制作有声书(2)

    切分语句 软件project的一条定律是数据和代码分离.这样做会使代码更易于測试,即使输入的数据发生改变,你的代码也能够同意.甚至于,程序能在执行中实时下载新的数据.假设程序能在执行中下载新书岂不是更 ...

  3. Java基础知识强化之IO流笔记05:try...catch...finally包含的代码是运行期的

    1. 代码示例: 上面看到的第13行:  Date  d = null;(这里必须初始化) 第14~20行使用try...catch...finally包含代码,这里的代码已经变成运行期代码.此时我们 ...

  4. Java基础知识强化18:抽象类、接口的区别 和 选择性实现接口方法

    1.抽象类和接口的区别 抽象类里面可以有非抽象的方法(可以没有抽象方法),接口里只能有抽象方法. 抽象类中的抽象方法声明时不能有大括号,而接口中的所有方法都没有大括号.  抽象类(abstract c ...

  5. SQL Server 存储过程分页

    每每面试,总会有公司问到分页.在下不才,在这里写几种分页,望路过的各位大神尽情拍砖. 先从创建数据库说起.源码如下 一.创建数据库 /********************************* ...

  6. Android虚拟机GenyMotion

    GenyMotion:需要VirtualBox,安装后可以选择机型,这个应该是Android for x86的一个改进版虚拟机,在原版的基础上针对不同机型用了和原机型同样的GUI,但是发现缺少了Goo ...

  7. cas sso单点登录系列6_cas单点登录防止登出退出后刷新后退ticket失效报500错

    转(http://blog.csdn.net/ae6623/article/details/9494601) 问题: 我登录了client2,又登录了client3,现在我把client2退出了,在c ...

  8. NOI 191钉子和小球.cpp

    #include<iostream> #include<cstdio> #include<cstring> using namespace std; ][]; in ...

  9. MESH

    本文由博主(YinaPan)原创,转载请注明出处:http://www.cnblogs.com/YinaPan/p/Unity_meshtest.html  A class that allows c ...

  10. arp断网攻击解决办法

    局域网中有这个提示arp断网攻击是正常的,说明防火墙已经拦截了,是有人用P2P工具控制你的网速,或者是局域网有机器中病毒了也会有这样的提示,不过不用担心,今天给大家带来几个防止arp断网攻击的办法,希 ...