我想编写一个带有数学函数(/,x,+,-)的函数,一个以数字开头的数字,以及一个数字列表。然后,应该返回一个列表。
第一个元素是起始编号,第二个元素是起始编号的值加/减/乘以给定列表的第一个数字。第三个元素是前一个结果的结果加上/减去/时间/除以给定列表的第二个结果,依此类推。
如果我告诉代码要使用哪个函数,我将使所有工作正常,但是如果我想让用户输入他想要的数学函数,则类型有问题。例如,尝试:t(/)会给出modalDraggableClickOutside('#modal-example', 'iframeLoaded', 'Modal shown');
,但是如果将其放在类型的开头,则会失败。
是否存在区分这些功能的特定类型(/,x,+,-)?还是有另一种成功编写此函数的方法?
Fractional a => a -> a -> a
正确的解决方案是这样的:
prefix :: (Fractional a, Num a) => a -> a -> a -> a -> [a] -> [a]
prefix (f) a b = [a] ++ prefix' (f) a b
prefix' :: (Fractional a, Num a) => a -> a -> a -> a -> [a] -> [a]
prefix' (z) x [] = []
prefix' (z) x y = [x z (head y)] ++ prefix' (z) (head (prefix' (z) x y)) (tail y)
答案 0 :(得分:3)
是否存在区分这些功能的特定类型(
/
,*
,+
,-
)?
我看不出这样做的理由。为什么\x y -> x+y
被认为比\x y -> x + y + 1
更好。确保将两个数字相加是大多数人认为更“纯”的事情。但是将自己限制为特定的功能子集很奇怪。对于某些功能\x y -> f x y - 1
“发生”等于(+)
的情况,也有可能出现,除了编译器无法确定。
类型检查将确保如果给定列表包含字符串等,则不能传递对数字进行操作的函数。但是,有意地进一步限制它不是很有用。为什么要阻止程序员将函数用于不同目的?
还是有另一种方法可以成功编写此函数?
您在这里描述的是scanl :: (b -> a -> b) -> b -> [a] -> [b]
函数。如果我们用scanl
调用scanl f z [x1, x2, ..., xn]
,那么我们将获得一个列表[z, f z x1, f (f z x1) x2, ...]
。 scanl
可以定义为:
scanl :: (b -> a -> b) -> b -> [a] -> [b]
scanl f = go
where go z [] = [z]
go z (x:xs) = z : go (f z x) xs
因此,我们首先发出 accumulator (从初始值开始),然后使用旧的f z x
,{ {1}}列表的开头,然后递归到列表的末尾。
答案 1 :(得分:2)
如果要限制这四个操作,只需自己定义类型:
data ArithOp = Plus | Minus | Times | Div
as_fun Plus = (+)
as_fun Minus = (-)
as_fun Times = (*)
as_fun Div = (/)