我正在尝试在 Haskell 中编写一个简单的高阶函数,它需要两个参数:
- 任何类型的函数列表。
- (数字或
String
s 或Bool
ean 等)的列表 --> 任何类型
该函数应该将第一个列表中的所有函数应用于第二个列表中的所有元素,将值存储在一个列表中,然后返回该列表。该程序的一个例子是:
Main> apply [(^2),(^3),(^4)] [2..8]
--result: --[4,8,9,16,25,27,32,36,49,64,81,125,128,216,256,343,512,625,1296,2401,4096]
函数的类型必须是:
apply :: Ord u => [v->u]->[v]->[u]
为此,我使用了两个辅助函数并使用了递归。我的程序是这样的:
apply :: Ord u => [v->u]->[v]->[u]
apply p s = myApply p s [] --line 59--
myApply :: Ord u => [v->u]->[u]->[u]->[u]
myApply f_list num_list starterlist
| null f_list = starterlist
| otherwise = myApply (tail f_list) (num_list) ( applyList (head f_list) num_list starterlist )
applyList :: Ord u => (v->u)->[u]->[u]->[u]
applyList f num_list starterlist
| null num_list = starterlist
| otherwise = applyList f (tail num_list) ( (head num_list) : starterlist )
我得到错误:
ERROR "Lab2.hs":59 - Inferred type is not general enough
*** Expression : applyList
*** Expected type : Ord a => (b -> a) -> [a] -> [b] -> [a]
*** Inferred type : Ord a => (a -> a) -> [a] -> [a] -> [a]
知道类型有什么问题吗?
最佳答案
您收到此错误的原因是因为存在冲突的类型签名:
apply :: <b>Ord u => [v->u]->[v]->[u]</b>
apply p s = <b>myApply p s []</b> --line 59--
myApply :: <b>Ord u => [v->u]->[u]->[u]->[u]</b>
myApply f_list num_list starterlist
| null f_list = starterlist
| otherwise = myApply (tail f_list) (num_list) ( applyList (head f_list) num_list starterlist )
如您所见,apply
函数立即调用 myApply
函数。由于 myApply
有签名 [v -> u] -> [u] -> [u] -> [u]
,这意味着 apply
只能有签名 [v->u] -> [u] -> [u]
.
快速解决方法是将 myApply
和 myApplyList
概括 到 [v -> u] -> [v] -> [u] -> [u]
。现在编译也会检测到您在 applyList
函数中犯的错误:您忘记在 head num_list
上调用 f
。所以你可以修复它并获取以下代码:
apply :: Ord u => [v->u]->[v]->[u]
apply p s = myApply p s [] --line 59--
myApply :: Ord u => [v->u]-><b>[v]</b>->[u]->[u]
myApply f_list num_list starterlist
| null f_list = starterlist
| otherwise = myApply (tail f_list) (num_list) ( applyList (head f_list) num_list starterlist )
applyList :: Ord u => (v->u)-><b>[v]</b>->[u]->[u]
applyList f num_list starterlist
| null num_list = starterlist
| otherwise = applyList f (tail num_list) ( (<b>f (</b>head num_list<b>)</b>) : starterlist )
尽管如此,这段代码非常不优雅,并且使用了许多函数和参数的方式。您可以将其完全替换为单个列表推导:
apply :: [v -> u] -> [v] -> [u]
apply fs xs = [f x | f <- fs, x <- xs]
根据您的评论,您还必须在该过程的后期对值进行排序,您可以使用 sort::Ord a => [a] -> [a]
内置函数来执行此操作:
-- sorting variant
apply :: <b>Ord u =></b> [v -> u] -> [v] -> [u]
apply fs xs = <b>sort</b> [f x | f <- fs, x <- xs]
这会生成所需的结果:
Prelude Data.List> (\fs xs -> sort [f x | f <- fs, x <- xs]) [(^2),(^3),(^4)] [2..8]
[4,8,9,16,16,25,27,36,49,64,64,81,125,216,256,343,512,625,1296,2401,4096]
关于function - 错误 - 推断类型不够通用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43184002/