我正在考虑像Ruby这样的纯面向对象语言,其中包括数字,int,浮点数和字符串在内的所有内容本身就是对象.这与纯函数式语言是一回事吗?例如,在Haskell中,Numbers和Strings是否也起作用?
我知道Haskell基于lambda演算,它将所有内容(包括数据和操作)表示为函数.对我来说,"纯粹的函数式语言"将所有内容都作为一个函数进行建模,并且保持一个函数最常返回相同输出且具有相同输入且没有状态的定义,这似乎是合乎逻辑的.
一个纯粹的 功能类似于一个数学函数,在那里与"现实世界",也不副作用没有交互的功能.从更实际的角度来看,这意味着纯函数不能:
所有这些限制使得更容易推理纯函数而不是非纯函数.然后,大多数函数应该是纯函数,以便程序可以减少错误.
在像Haskell这样的庞大类型系统的语言中,如果函数是纯粹的或者不是纯粹的,读者可以从一开始就知道,使得连续阅读更容易.
在Python中,这些信息可以由@pure放在函数顶部的装饰器模拟.我也希望那个装饰器实际上做一些验证工作.我的问题在于这种装饰器的实现.
现在我只是看一下流行语的功能的源代码,如globalor random或print抱怨,如果找到其中一个.
import inspect
def pure(function):
source = inspect.getsource(function)
for non_pure_indicator in ('random', 'time', 'input', 'print', 'global'):
if non_pure_indicator in source:
raise ValueError("The function {} is not pure as it uses `{}`".format(
function.__name__, non_pure_indicator))
return function
Run Code Online (Sandbox Code Playgroud)
然而,感觉就像一个奇怪的黑客,根据你的运气可能会或可能不会工作,你能帮我写一个更好的装饰?
python formal-verification metaprogramming decorator purely-functional
我正在研究Okasaki的Purely Functional Data Structures并尝试构建F#实现的东西.我也正在阅读本书中列出的练习(有些非常具有挑战性).好吧,我坚持练习3.4,它要求修改WeightBiasedLeftistHeap的合并功能,使其在单个传递中执行,而不是原始的2传递实现.
我还没弄清楚如何做到这一点,并希望得到一些建议.在SO上有另一篇文章,其中一个人通过几乎内联makeT函数在SML中完成它.我开始走这条路线(在评论部分3.4首先尝试.但是放弃了这种方法,因为我认为这真的不是在一次传递中执行(它仍然是'直到达到叶子然后展开并重建树).我在解释那仍然是两次合并时错了吗?
这是我完整实施WeightBiasedLeftistHeap的链接.
以下是我在F#中尝试这样做的失败:
type Heap<'a> =
| E
| T of int * 'a * Heap<'a> * Heap<'a>
module WeightBiasedLeftistHeap =
exception EmptyException
let weight h =
match h with
| E -> 0
| T(w, _,_,_) -> w
let makeT x a b =
let weightA = weight a
let weightB = weight b
if weightA >= weightB then
T(weightA + weightB + 1, x, a, b)
else
T(weightA + weightB …Run Code Online (Sandbox Code Playgroud) f# functional-programming purely-functional data-structures tailrecursion-modulo-cons
我记得看到一个演示文稿,其中SPJ说懒惰评估迫使他们保持Haskell纯粹(或沿着那条线).我经常看到许多Haskellers说同样的话.
所以,我想了解懒惰的评估策略是如何迫使他们保持Haskell纯粹而不是严格的评估策略?
让我们定义一个树T:
A
/ \
B C
/ \
D E
Run Code Online (Sandbox Code Playgroud)
假设一个新节点被添加到E,产生T':
A
/ \
B C
/ \
D E
\
G
Run Code Online (Sandbox Code Playgroud)
在一个可变的语言中,这是一个简单的任务 - 只需更新E的孩子,我们就完成了.然而,在一个不可变的世界中,有必要首先知道E的路径,然后从E +新子导出E',然后导出B',然后导出A'(= T').
这很麻烦; 理想情况下,会有一些函数可以获取E和G(可能还有T)的值并产生T',而不提供到E的路径.
我看到两种可能的方法来解决这个问题:
考虑到合理的表现,我想要的是什么?非常感谢任何输入!
所以我正在使用Racket Scheme自学编程功能,到目前为止我都喜欢它.作为我自己的练习,我一直在尝试以纯粹的功能方式实现一些简单的任务.我知道不变性是功能风格的重要组成部分,但我想知道是否有任何时候它是可以的.
我想到了一种函数在与filter一起使用时从字符串列表中删除非唯一字符串的有趣方式,如下所示:
(define (make-uniquer)
(let ([uniques '()])
(lambda (x)
(if (not (member x uniques))
(set! uniques (cons x uniques))
#f))))
(define (uniquify x)
(let ([uniquer (make-uniquer)])
(filter uniquer x)))
Run Code Online (Sandbox Code Playgroud)
如您所见,make-uniquer在一个字符串列表上返回一个闭包,以便与唯一性进行比较,这样它就可以作为过滤器的简单谓词.但我破坏性地更新了封闭式清单.这是不好的形式,还是以这种方式改变本地封闭变量?
lisp scheme functional-programming mutability purely-functional
我很熟悉在F#中没有等效的"return"关键字.
然而,我们最近遇到了一个问题,我们需要一个包含许多步骤的工作流程,其中每个步骤都可以返回好的或坏的结果.如果在任何步骤中发现不良结果,我们想退出工作流程 - 并提前退出!
我们通过有效地检查每个步骤中的错误(即函数)来解决它,但我不认为这是正确的方法 - 它是低效的,我们不提前退出.
工作流程中的示例函数如下:
let StepB stepAResult someParameters =
match stepAResult with
| Good(validResourceData) ->
// Do current step processing
// Return current step result
| Error(error) -> error |> Result.Error
Run Code Online (Sandbox Code Playgroud)
工作流本身如下:
let Workflow someParameters =
let stepAResult = StepA someParameters
let stepBResult = StepB stepAResult someParameters
let stepCResult = StepC stepBResult someParameters
let stepDResult = StepD stepCResult someParameters
stepDResult
Run Code Online (Sandbox Code Playgroud)
因此,每个样本函数都会接收上一个函数的结果,并且只有在没有错误时才执行当前步骤!
我遇到的问题是,如果StepA因错误而失败,则仍会调用其他所有步骤.
是否存在"早期返回"的"功能"方式,而不是调用工作流中的每个功能,我们必须每次检查错误?
有人可以展示一个简单的例子,其中状态monad可以比直接传递状态更好吗?
bar1 (Foo x) = Foo (x + 1)
Run Code Online (Sandbox Code Playgroud)
VS
bar2 :: State Foo Foo
bar2 = do
modify (\(Foo x) -> Foo (x + 1))
get
Run Code Online (Sandbox Code Playgroud) 给定一个java.lang.reflect.Method对象,无论如何都要确定该方法是否是纯粹的功能(即,给定相同的输入,它将始终产生相同的输出并且它是无状态的.换句话说,该功能不依赖于其环境)?
我正在尝试学习函数式编程和Scala,所以我正在阅读Chiusano和Bjarnason的"Scala中的函数式编程".我无法理解左侧折叠和折叠右侧方法在列表的情况下做了什么.我在这里环顾四周,但我找不到一些初学友好的东西.所以本书提供的代码是:
def foldRight[A,B](as: List[A], z: B)(f: (A, B) => B): B = as match {
case Nil => z
case Cons(h, t) => f(h, foldRight(t, z)(f))
}
def foldLeft[A,B](l: List[A], z: B)(f: (B, A) => B): B = l match {
case Nil => z
case Cons(h,t) => foldLeft(t, f(z,h))(f)
}
Run Code Online (Sandbox Code Playgroud)
Cons和Nil是:
case class Cons[+A](head: A, tail: List[A]) extends List[A]
case object Nil extends List[Nothing]
Run Code Online (Sandbox Code Playgroud)
那么左右实际折叠的是什么呢?为什么需要"实用"方法?有许多其他方法使用它们,我也很难理解它们,因为我没有得到这两个.
f# ×2
haskell ×2
decorator ×1
foldleft ×1
immutability ×1
java ×1
lisp ×1
monads ×1
mutability ×1
python ×1
reflection ×1
scala ×1
scheme ×1
state-monad ×1
tree ×1
zipper ×1