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

Function Haskell中是否有特定类型的数学函数?,function,haskell,types,Function,Haskell,Types,我想写一个函数,它包含一个数学函数/,x,+,-,一个以数字开头的数字和一个数字列表。然后,它应该返回一个列表 第一个元素是起始数字,第二个元素是起始数字加/减/乘/除以给定列表的第一个数字。第三个元素是前一个结果加/减/乘/除以给定列表的第二个结果的结果,依此类推 如果我告诉代码使用哪一个函数,我就可以让一切正常工作,但是如果我想让用户输入他想要的数学函数,类型就有问题。Trying:t/例如给出了分数a=>a->a->a,但是如果你把它放在类型的开头,它就失败了 是否有特定类型来区分这些函数

我想写一个函数,它包含一个数学函数/,x,+,-,一个以数字开头的数字和一个数字列表。然后,它应该返回一个列表

第一个元素是起始数字,第二个元素是起始数字加/减/乘/除以给定列表的第一个数字。第三个元素是前一个结果加/减/乘/除以给定列表的第二个结果的结果,依此类推

如果我告诉代码使用哪一个函数,我就可以让一切正常工作,但是如果我想让用户输入他想要的数学函数,类型就有问题。Trying:t/例如给出了分数a=>a->a->a,但是如果你把它放在类型的开头,它就失败了

是否有特定类型来区分这些函数/,x,+,-?或者是否有其他方法可以成功编写此函数

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)
正确的解决方案如下:

prefix (-) 0 [1..5]

[0,-1,-3,-6,-10,-15]
是否有特定类型来区分这些函数/、*、+、-

我看不出有什么理由这么做。为什么认为\x y->x+y优于\x y->x+y+1。当然,增加两个数字是大多数人认为更纯净的东西。但将自己局限于特定的函数子集是很奇怪的。对于某些函数\x y->f x y-1也可能恰好等于+,除非编译器无法确定这一点

类型检查将确保不能传递对数字进行操作的函数,因为列表包含字符串等。但有意进一步限制这一点并不是很有用。为什么要阻止程序员将函数用于不同的目的

或者是否有其他方法可以成功编写此函数

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)
您在这里描述的是函数。如果我们用scanlfz[x1,x2,…,xn]调用scanl,那么我们得到一个列表[z,fzx1,fzx1x2,…]。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
因此,我们首先发出以初始值开始的累加器,然后用旧累加器z和列表的头部x将累加器更新为fzx,并在列表的尾部递归

是否有特定类型来区分这些函数/、*、+、-

我看不出有什么理由这么做。为什么认为\x y->x+y优于\x y->x+y+1。当然,增加两个数字是大多数人认为更纯净的东西。但将自己局限于特定的函数子集是很奇怪的。对于某些函数\x y->f x y-1也可能恰好等于+,除非编译器无法确定这一点

类型检查将确保不能传递对数字进行操作的函数,因为列表包含字符串等。但有意进一步限制这一点并不是很有用。为什么要阻止程序员将函数用于不同的目的

或者是否有其他方法可以成功编写此函数

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)
您在这里描述的是函数。如果我们用scanlfz[x1,x2,…,xn]调用scanl,那么我们得到一个列表[z,fzx1,fzx1x2,…]。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

因此,我们首先发出以初始值开始的累加器,然后用旧累加器z和列表的头部x将累加器更新为f z x,并在列表的尾部递归。

如果您想限制这四个操作,只需自己定义类型:

data ArithOp = Plus | Minus | Times | Div

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

如果要限制这四种操作,只需自己定义类型:

data ArithOp = Plus | Minus | Times | Div

as_fun Plus = (+)
as_fun Minus = (-)
as_fun Times = (*)
as_fun Div = (/)
看起来scanl:scanl-0[1..5]将返回[0,-1,-3,-6,-10,-15]。但是没有理由把自己局限于数学函数。签名就是scanl::b->a->b->b->a->[b]。可以使用任何类型的函数和元素。我不明白你为什么要限制一些有用的东西?例如,您可以编写scanl flip:[][1,4,2,5]来获得所有反向前缀:[[]]、[1]、[4,1]、[2,4,1]、[5,2,4,1]。您只需要更多参数。前缀::分数a,数值a=>a->a->a->a->a->[a]->[a]。类似的修改适用于前缀“”。但请参阅下面的答案,以了解可以为前缀提供的更一般的类型。这看起来像scanl:scanl-0[1..5]将返回[0,-1,-3,-6,-10,-15]。但是没有理由把自己局限于数学函数。签名就是scanl::b->a->b->b->a->[b]。可以使用任何类型的函数和元素。我不明白你为什么要限制一些有用的东西?例如,您可以编写scanl flip:[][1,4,2,5]来获得所有反向前缀:[[]]、[1]、[4,1]、[2,4,1]、[5,2,4,1]。您只需要更多参数。前缀::分数a,数值a=>a->a->a->a->a->[a]->[a]。类似的修改适用于前缀“”。但请参阅下面的答案,了解您可以为前缀提供的更一般的类型。