Haskell中的变量问题

问题描述

很简单的一个问题,、在Haskell中实现下面Lisp代码的功能。唉,Haskell啊,纯函数式啊,Monad啊,我刚学啊,不知道怎么办啊 (define inc (n) (lambda (i) (incf n i))) 问题补充:cloverprince 写道

解决方案

真的?但是我曾经发现,用Haskell写的一些代码,长度仅有等价的C或者Python代码的一半。比如这个,高阶函数和List Comprehension比循环简洁的多http://cloverprince.iteye.com/blog/319072但是,真正成问题的是,我不够聪明,以至于有时候我无法指出如何写出精简的代码。
解决方案二:
可以使用haskell的lambda实现,如下即可:inc n = i -> incf n i
解决方案三:
可以使用haskell的lambda实现,如下即可:inc n = i -> incf n i
解决方案四:
试试转换一下思维,能用命令式实现的一定能够用函数式方法实现。
解决方案五:
Haskell里变量是不可变的。函数是没有副作用的。所以,不可能去修改一个变量的值。其实,你的意思是,“调用”一个函数的时候,和某个符号(变量名)x相关的状态被改变;下次调用另一个函数,而且这个函数需要依赖于这个变量x,那么这个函数将返回不同的值。这样也做不到,因为既然是“函数”,那么给定相同的自变量,返回的值总是相同的,否则就不是“函数”了。可以用State monad模拟这种行为。实际上GHC已经包含了State这种类型。可以参考这个:http://www.haskell.org/haskellwiki/State_Monad,说实话,不太直观,但后面介绍了标准库的用法。下面是一个简单的实现。我们假设状态是Int型,定义为StateType。我们定义一种容器:保存一个值,附带当前的状态。就是那个ValueWithState。所谓“当前状态”,就是那个可以随便改变的Int值。然后定义一个Action,里面存了一个函数,输入旧状态,输出一个值和一个新状态。可以认为Action就是一步“操作”(可以和之前所有的运算结果相关),同时这步操作可能会改变当前状态。也就理解成“可能会发生副作用的操作”。我们定义几个特殊操作第一个是return x。函数return输入变量x产生一个操作,产生的这个操作不改变状态,但是会改变“当前值”,且“当前值”就是x。第二个是set n。这个操作会直接把当前状态改成n,但是这个操作本身不返回新的值。这里不得不让它返回()。第三个是get。这个操作会把“当前状态”放到“当前值”里,也就是“读取那个隐藏的状态”。然后就是add n了。其实有get和set就能随意改变“状态”了,加上这个add比较方便,就是把当前状态增加一些,不返回值(返回())。然后,为了让它成为Monad,我们必须允许把两个“Action”捆绑在一起,让它们看上去像一个Action。(注意,第二个Action可能依赖于第一个Action的运行结果,所以>>=的定义是 Monad a -> (a -> Monad b) -> Monad b)实现Monad要求的>>=函数,就是把“把两个Action捆绑起来”装得像一点。稍微有点麻烦。“完成两部操作”,就是:首先,在已知初始状态state0的情况下,完成第一步操作。然后,利用第一步操作的结果value1,制造出第二个操作(因为第二个操作可能依赖第一个)。然后已知第一步操作后的状态state1的条件下,执行第二个操作。这样得到的新值和新状态就是整体执行的结果了。然后就可以尽情地用do notation执行一些“看上去像命令式”的过程了。module Main wheretype StateType = Intdata ValueWithState valueType = ValueWithState StateType valueType deriving Showdata Action resultType = Action { doAction :: StateType -> (ValueWithState resultType)}get = Action { doAction = oldState -> ValueWithState oldState oldState}set n = Action { doAction = oldState -> ValueWithState n ()}addOne = Action { doAction = oldState -> ValueWithState (oldState+1) ()}add n = Action { doAction = oldState -> ValueWithState (oldState+n) ()}instance Monad Action where return result = Action { doAction = oldState -> ValueWithState oldState result } action1 >>= f = Action { doAction = state0 -> let ValueWithState state1 value1 = doAction action1 state0 action2 = f value1 ValueWithState state2 value2 = doAction action2 state1 in ValueWithState state2 value2 }someAction = do add 3 s1 <- return "Hello" add 2 s2 <- return "World" s3 <- get return (s1 ++ s2 ++ (show s3))ValueWithState finalState finalValue = doAction someAction 42main = do putStrLn (show finalState) putStrLn finalValue

时间: 2024-10-21 23:38:01

Haskell中的变量问题的相关文章

浅析Nginx配置文件中的变量的编写使用_nginx

nginx 的配置文件使用的就是一门微型的编程语言,许多真实世界里的 Nginx 配置文件其实就是一个一个的小程序.当然,是不是"图灵完全的"暂且不论,至少据我观察,它在设计上受 Perl 和 Bourne shell 这两种语言的影响很大.在这一点上,相比 Apache 和 Lighttpd 等其他 Web 服务器的配置记法,不能不说算是 Nginx 的一大特色了.既然是编程语言,一般也就少不了"变量"这种东西(当然,Haskell 这样奇怪的函数式语言除外了).

Xcode中修改变量名、类名及字符串的替换操作

Xcode中修改变量名.类名及字符串的替换操作         在做iOS开发代码优化的工作时,优化代码结构之前,我们应该先整理好工程的外貌,将文件和类的命名进行规范,在Xcode中为我们提供了方便而强大的名称修改功能. 第一步:修改类名         将鼠标点击放在类的名称上,选择Xcode工具栏中的edit->refactor->rename: 之后,将类名更改为我们需要的模式点击preview,记得将下面的关联文件勾选: Xcode会为我们检测出需要更改的地方,浏览无误后点击save.

c c++编程-c++中 数据类型 变量名(常量) 这样的无法结构是什么意思呢?

问题描述 c++中 数据类型 变量名(常量) 这样的无法结构是什么意思呢? 这是一段c++程序,请问中间那句 double r(3.0)是什么意思?为何 3.0用括号包着?r又不是一个函数.. 解决方案 对变量的初始化的另一种形式. C++支持两种形式的初始化:1:使用赋值操作符的显示语法形式.如:int ival=1024;2: 隐式形式,初始值被放在括号中.如:int ival (1024); 解决方案二: 这样的无法结构是什么意思呢?可能是 数据类型 没有相应的构造函数,具体需要看 数据类

驱动 架构-在驱动程序中对硬件的初始化和在设备中对变量的初始化有什么联系和区别?

问题描述 在驱动程序中对硬件的初始化和在设备中对变量的初始化有什么联系和区别? 在驱动程序中对硬件的初始化和在设备中对变量的初始化有什么联系和区别? 解决方案 在设备中对变量的初始化???没明白这句话

实例详细讲解ASP教程之ASP中使用变量的方法

变量|教程 变量用于存储信息. 假如在子程序之外声明变量,那么这个变量可被ASP文件中的任何脚本改变.假如在子程序中声明变量,那么当子程序每次执行时,它才会被创建和撤销 实例: 声明变量 变量用于存储信息.本例演示如何声明变量,为变量赋值,并在程序中使用这个变量 <html><body><%dim namename="Donald Duck"response.write("My name is: " & name)%>&l

PHP教程:PHP编程中的变量生存周期

对于PHP的中的数据来源, 不外乎有俩种: 1. 来自代码中 对于代码中的变量(也就是直接量)来说, 变量分配/赋值在编译期, 活跃在执行器, 在请求关闭期被销毁.对于这些变量来说, 使用APC进行Opcode缓存, 则会缓存这部分变量的值. 而对于来自外部的变量, 变量分配/赋值在编译器后, 执行期前, 在请求关闭期被销毁,对于这些变量来说, 使用APC进行OpCode缓存, 是不会被缓存的. 今天就着重关注下外部变量的一个部分,GET来的数据的整个生命周期. 假设, 有如下请求到来:   而

如何在一个JSP页面中调用另一个JSP页面中的变量

在jsp学习中,经常需要在一个jsp页面中调用另一个jsp页面中的变量,下面就这几天的学习,总结一下. jsp页面之间的变量调用有多种方法: 1.通过jsp的内置对象-request对象获取参数: (1)通过超链接传参: 例:把a.jsp中i的值传到b.jsp中: 在a.jsp页面中的核心代码为: <a href="b.jsp?i=1">传参</a>     (说明:给i赋值时也可以用jsp表达式,例如i=<%变量名 %>) 在b.jsp页面中的核心

如何在xslt中使用变量

变量是我们编程时遇到最多的对象之一.它提供了在代码中存储数据以及代码 复用的机制.有没有办法在xslt中使用变量呢? 答案是可以的. 首先看看,如何使用变量来复用代码 <xsl:variable name="Header"> <tr> <td>属性名</td> <td>属性值</td> </tr> </xsl:variable> 我们通过这样定义就声明了一个叫做Header的变量,它代表了一

php中smarty变量修饰用法实例分析

 test.php代码: 1 2 3 4 5 6 7 8 9 <?php require 'libs/Smarty.class.php'; //包含Smarty类库文件 $smarty = new Smarty; //创建一个新的Smarty对象 $total = 12345; //对$total赋值 $smarty->assign("total",$total); //对模版中的变量赋值 $formatted_total = number_format($total);