在编程的运动,它首先要求编程的阶乘函数,然后计算的总和:1! + 2! + 3! +... n!在O(n)乘法(所以我们不能直接使用阶乘).我不是在寻找这个特定(微不足道)问题的解决方案,我正在尝试探索Haskell的能力,这个问题是我想要玩的玩具.
我认为Python的生成器可以很好地解决这个问题.例如 :
from itertools import islice
def ifact():
i , f = 1, 1
yield 1
while True:
f *= i
i += 1
yield f
def sum_fact(n):
return sum(islice(ifact(),5))
Run Code Online (Sandbox Code Playgroud)
然后我试图弄清楚Haskell中是否有类似于这个生成器的行为,我认为懒惰会让所有员工都没有任何额外的概念.
例如,我们可以用我的Python ifact替换
fact = scan1 (*) [1..]
Run Code Online (Sandbox Code Playgroud)
然后用以下方法解决练习:
sum n = foldl1 (+) (take n fact)
Run Code Online (Sandbox Code Playgroud)
我想知道这个解决方案是否真的与Python关于时间复杂性和内存使用的"等效".我会说Haskell的解决方案永远不会存储所有列表事实,因为它们的元素只使用一次.
我是对还是完全错了?
编辑:我应该更准确地检查:
Prelude> foldl1 (+) (take 4 fact)
33
Prelude> :sprint fact
fact = 1 : 2 : 6 : 24 …Run Code Online (Sandbox Code Playgroud) 我的一个学生写了一个看起来像这样的代码(它完全没有达到他所期望的那样):
t = [1,2,3]
for t[1] in "abcd":
print("hello")
Run Code Online (Sandbox Code Playgroud)
我以前从未见过这个,并且很确定它不会编译,但它确实正在修改 t[1](在循环之后t[1]设置d).
允许这种语法有什么意义?有没有用例?对我来说,唯一"可接受的"语法应该是:
for <variable_name> in <iterable>:
...
Run Code Online (Sandbox Code Playgroud)
<variable_name>标识符在哪里,没有别的.
这是将类型t的操作符转换为操作符的标准方法a->t吗?即,这是一个实现此功能的lib(fT如functionTransformer):
fT :: (t -> t -> t) -> (a -> t) -> (a -> t) -> (a -> t)
fT op f1 f2 = \x -> (f1 x) `op` (f2 x)
Run Code Online (Sandbox Code Playgroud)
(我们可以推广到fT :: (t1 -> t2 -> t) -> (t3 -> t1) -> (t3 -> t2) -> t3 -> t)
在学习Yesod时我问这个问题:在这个框架中,我们可以为字段添加验证条件,这要归功于checkBool.例如,我可以创建一个只接受大于100的值的字段:
smallIntField = checkBool (<= 100) "error: this entry has to be smaller than 100" intField
Run Code Online (Sandbox Code Playgroud)
感谢我的"函数变换器",我可以轻松地管理有界值: …
假设我有两个矩阵B,M并且我想执行以下语句:
B += 3*M
Run Code Online (Sandbox Code Playgroud)
我反复执行这个指令,所以我不想每次构建矩阵3*M(3可能会改变,只是为了使我只做一个标量矩阵产品).它是一个numpy函数,使这个计算"到位"?
更准确地说,我有一个标量列表as和一个矩阵列表Ms,我想执行两者中的"点积"(这两个操作数是不同类型的,实际上不是一个),也就是说:
sum(a*M for a, M in zip(as, Ms))
Run Code Online (Sandbox Code Playgroud)
该np.dot功能不能做我除了......