您好我想在Haskel中调用一些函数调用,但我无法弄清楚我做错了什么。更具体地说,我有一个函数f(a,b,c)= a + b + c,我想采用这样的int:
x = Sum(从i = 0到i = c)f(1,1,i)
到目前为止,我已经写过这个,但它甚至没有编译。你能救我吗?
f a b c = a+b+c
my_sum f a b c+1 =f a b c+1 + my_sum f a b c
我得到parse error in pattern my_sum
例如对于my_sum f 1 1 5
,结果将是f(1,1,5)+ f(1,1,4)+ f(1,1,3)+ f(1,1,2)+ F(1,1,1)
我不想使用列表
答案 0 :(得分:2)
n+k
模式不好
您的代码:
my_sum f a b c+1 =f a b c+1 + my_sum f a b c
包含c+1
形式的模式,其中A)应该有括号B)需要一个基本情况(我假设你想在c == 0
时停止)和C)是一个语法形式从语言中移除。
相反,如果需要,明确从c
中减去1,并确保处理基本情况:
my_sum f a b 0 = f a b 0
my_sum f a b n = f a b n + my_sum f a b (n-1)
这也有内存泄漏意味着它会以f1 + (f a b n' + (f a b n'' + (f a b n''' + (...
的形式构建一个大型计算。您可以通过在编译时使用累加器或更高级别的函数和优化来处理泄漏。
更清洁的解决方案
列表理解让我觉得这是最合理的解决方案:
sum [f a b i | i <- [0..c] ]
应用于广告f
,a
和最后b
的{{1}}函数的总和,其中i
的范围是i
到{{ 1}}包含。
答案 1 :(得分:0)
您无法在定义的左侧使用c+1
。由于你只是求和,如果你从0计数到c
或从c
倒数到0就没关系,所以你可以改为
my_sum f a b 0 = f a b 0
my_sum f a b c = f a b c + my_sum f a b (c - 1)
然后你可以用它作为
> let g x y z = x + y + z
> my_sum g 0 0 10
55
有关代码无法编译的原因的更多详细信息:每当定义左侧有模式时,例如
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
您只能匹配构造函数,名称(例如n
或c
)和文字(它们本质上是基本类型的构造函数。函数+
不是构造函数,它是属于Num
类型类的函数,因此您无法对其进行模式匹配。您之前看到列表模式匹配可能会感到困惑,因为它使用了运算符:
myListSum [] = 0
myListSum (x:xs) = x + myListSum xs
但事实上,:
是列表的Cons
构造函数,[]
是空列表构造函数。您可以将列表类型定义为
data [a] = [] | a : [a]
或者,如果您要用文字替换所有符号
data List a = Empty | Cons a (List a)
虽然它在现实中有点不同,因为定义列表的内容更多,但这是基本的想法。这意味着像
这样的模式f [] = ...
f (x:xs) = ...
相当于
f Empty = ...
f (Cons x xs) = ...
只需更方便的语法。
然而,Int
可以作为非常大的ADT定义为
data Int = -2147483648 | -2147483647 | ... | -1 | 0 | 1 | ... | 2147483646 | 2147483647
其中每个数字本身都是不同的构造函数。然后,您可以匹配任何单个数字,但不能匹配(x + 1)
或(x * 2)
,因为+
和*
不是构造函数,只是常规函数。 (注意:Int
实际上并没有以这种方式定义,因为那样效率非常低,它是在更原始的层次上定义的)
答案 2 :(得分:0)
您可以从列表表达式到非列表,递归表达式,手动内联和融合功能:
{-# LANGUAGE BangPatterns #-}
import Data.List
f a b c = a+b+c
g f a b c = sum . map (f a b) $ [0..c]
= foldl' (\ !x y -> x + f a b y) 0 $ enumFromTo 0 c
= h 0 0 where
h !acc i | i > c = acc
| otherwise = h (acc + f a b i) (i+1)
对于c
的大值,严格注释会阻止不受控制的build-up of thunks and stack overflow。