免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6119 | 回复: 18
打印 上一主题 下一主题

怎么才叫 lazy 呢? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-31 19:59 |只看该作者 |倒序浏览
如果哪里不正确,请指出,改之


需要时才计算,不需要时就不计算
才叫 lazy!


看一个例子:

  1. --test.hs
  2. module Main where

  3. myIf::Bool->Int->Int->Int
  4. myIf cond a b = if cond
  5.                 then a
  6.                 else b
复制代码

这里定义了一个简单的模拟 if..then..else..表达式的函数 myIf
其类型为Bool->Int->Int->Int
其接受三个参数(虽然表达不正确,就这样形象的说吧)
功能:当 cond 为 True 返回 a,否则返回 b

加载此模块
:l test.hs
键入:
myIf ("fst" == "Fst") 1 (2+3)

你知道这个函数怎么运行的吗?
如果你没接触过函数式编程,
你会认为:解释器先把 ("fst" == "Fst") 和 (2+3) 分别计算为 False 和 5,然后把 False、1 和 5 绑定到 myIf 函数的三个参数 cond、a 和 b上,因为 cond 为 False,所以返回 5.

哈哈,错了!
注意:“当需要时才计算,不需要时就不计算”这句话!

add 函数运行的过程为:
解释器把 ("fst" == "Fst")、1、(2+3) 三个参数绑定到 myIf 函数的三个参数 cond、a 和 b 上,返回 if..then..else表达式的值。
这时需要求if "fst" == "Fst" then 1 else (2+3) 表达式的值,先计算 "fst" == "Fst" 为 False, 所以返回 (2+3) 表达式的值,
这时需要求 (2+3) 表达式的值,计算 (2+3) 表达式的值为 5,
所以返回 5。

[ 本帖最后由 izhier 于 2009-3-31 20:38 编辑 ]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2009-03-31 21:17 |只看该作者
解释完全错误!

你这个是 normal order 和 application order 的区别,和是不是 lazy 没太大关系。
很遗憾,Haskell 是 application order 的,也就是说,

你会认为:解释器先把 ("fst" == "Fst") 和 (2+3) 分别计算为 False 和 5,然后把 False、1 和 5 绑定到 myIf 函数的三个参数 cond、a 和 b上,因为 cond 为 False,所以返回 5.

这样子的。

你认识的正好是错误的。

你可以用 myIf (1==2) (2/0) (2+3) 来检验。

论坛徽章:
0
3 [报告]
发表于 2009-03-31 21:51 |只看该作者

  1. Main> myIf False (2/0) 1
  2. ERROR - Cannot infer instance
  3. *** Instance   : Fractional Int
  4. *** Expression : myIf False (2 / 0) 1
复制代码

这个提示是 Cannot infer,说明类型不匹配,根本没有通过类型推导系统
(2/0) 不是 Int 类型

  1. real world haskell 第二章 Understanding Evaluation by Example 中有讲
复制代码

[ 本帖最后由 izhier 于 2009-3-31 21:59 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2009-03-31 21:52 |只看该作者

回复 #2 flw 的帖子

flw理解完全错误。你可以用myIf (1==2) undefined (2+3)来检验。

论坛徽章:
0
5 [报告]
发表于 2009-03-31 21:57 |只看该作者
原帖由 izhier 于 2009-3-31 21:51 发表

Main> myIf False (2/0) 1
ERROR - Cannot infer instance
*** Instance   : Fractional Int
*** Expression : myIf False (2 / 0) 1

这个提示是 Cannot infer,说明类型不匹配
我想问一下: 0 是 Frac ...


类型不匹配是因为2/0类型为(Fractional t) => t,而你的myIf的类型声明中,该参数为Int。

你把2/0换为div 2 0就好了。

论坛徽章:
0
6 [报告]
发表于 2009-03-31 21:59 |只看该作者

  1. g=g

  2. f b x y = if b then x else y
复制代码


执行 g 会陷入无限循环。

f True 1 g 得到 1。

f False 1 g 无限循环。

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
7 [报告]
发表于 2009-03-31 22:00 |只看该作者
哦?
我换成 2 `div` 0 之后确实是可以的。
难道 Haskell 居然是 normal order 的?

论坛徽章:
0
8 [报告]
发表于 2009-03-31 22:00 |只看该作者

回复 #5 roy_hu 的帖子

改回来了,发现你回贴了,晚了一步呀

[ 本帖最后由 izhier 于 2009-3-31 22:05 编辑 ]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2009-03-31 22:01 |只看该作者
原帖由 win_hate 于 2009-3-31 21:59 发表

g=g

f b x y = if b then x else y


执行 g 会陷入无限循环。

f True 1 g 得到 1。

f False 1 g 无限循环。

这段代码好面熟啊。

论坛徽章:
0
10 [报告]
发表于 2009-03-31 22:03 |只看该作者
原帖由 flw 于 2009-3-31 22:01 发表

这段代码好面熟啊。


我以前没贴过啊?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP