简体   繁体   English

Haskell中的数学函数是否有特定类型?

[英]Is there a specific type for mathematical functions in Haskell?

I want to write a function that takes a mathematical function (/,x,+,-), a number to start with and a list of numbers. 我想编写一个函数,该函数需要一个数学函数(/,x,+,-),一个以数字开头的数字和一个数字列表。 Then, it's supposed to give back a list. 然后,应该返回一个列表。

The first element is the starting number, the second element the value of the starting number plus/minus/times/divided by the first number of the given list. 第一个元素是起始编号,第二个元素是起始编号的值加/减/乘以给定列表的第一个数字。 The third element is the result of the previous result plus/minus/times/divided by the second result of the given list, and so on. 第三个元素是前一个结果的结果加上/减去/时间/除以给定列表的第二个结果,依此类推。

I've gotten everything to work if I tell the code which function to use but if I want to let the user input the mathematical function he wants, there are problems with the types. 如果我告诉代码要使用哪个函数,我将使所有工作正常,但是如果我想让用户输入他想要的数学函数,则类型有问题。 Trying :t (/) for example gives out Fractional a => a -> a -> a , but if you put that at the start of your types, it fails. 例如,尝试:t(/)给出Fractional a => a -> a -> a ,但是如果将其放在类型的开头,它将失败。

Is there a specific type to distinguish these functions (/,x,+,-)? 是否存在区分这些功能的特定类型(/,x,+,-)? Or is there another way to write this function succesfully? 还是有另一种成功编写此函数的方法?

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)

A right solution would be something like this: 正确的解决方案是这样的:

prefix (-) 0 [1..5]

[0,-1,-3,-6,-10,-15]

Is there a specific type to distinguish these functions ( / , * , + , - )? 是否存在区分这些功能的特定类型( /*+- )?

I don't see a reason to do this. 我看不出这样做的理由。 Why is \\xy -> x+y considered "better" than \\xy -> x + y + 1 . 为什么\\xy -> x+y被认为比\\xy -> x + y + 1 “更好”。 Sure adding two numbers is something that most will consider more "pure". 确保将两个数字相加是大多数人认为更“纯”的事情。 But it is strange to restrict yourself to a specific subset of functions. 但是将自己限制为特定的功能子集很奇怪。 It is also possible that for some function \\xy -> fxy - 1 "happens" to be equal to (+) , except that the compiler can not determine that. 对于某些函数\\xy -> fxy - 1 “ happens”也有可能等于(+) ,除了编译器无法确定。

The type checking will make sure that one can not pass functions that operate on numbers, given the list contains strings, etc. But deliberately restricting this further is not very useful. 类型检查将确保在给定列表包含字符串等的情况下,不能传递对数字进行操作的函数。但是,有意地进一步限制它并不是很有用。 Why would you prevent programmers to use your function for different purposes? 为什么要阻止程序员将函数用于不同目的?

Or is there another way to write this function succesfully? 还是有另一种成功编写此函数的方法?

What you here describe is the scanl :: (b -> a -> b) -> b -> [a] -> [b] function. 您在这里描述的是scanl :: (b -> a -> b) -> b -> [a] -> [b]函数。 If we call scanl with scanl fz [x1, x2, ..., xn] , then we obtain a list [z, fz x1, f (fz x1) x2, ...] . 如果我们用scanl fz [x1, x2, ..., xn]调用scanl ,那么我们将获得一个列表[z, fz x1, f (fz x1) x2, ...] scanl can be defined as: 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

We thus first emit the accumulator (that starts with the initial value), and then "update" the accumulator to fzx with z the old accumulator, and x the head of the list, and recurse on the tail of the list. 因此,我们首先发出累加器 (从初始值开始),然后将累加器“更新”为fzx其中z为旧累加器, x为列表的开头,然后递归到列表的末尾。

If you want to restrict to these four operations, just define the type yourself: 如果要限制这四个操作,只需自己定义类型:

data ArithOp = Plus | Minus | Times | Div

as_fun Plus = (+)
as_fun Minus = (-)
as_fun Times = (*)
as_fun Div = (/)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM