Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
调用Haskell中另一个函数的内部函数_Haskell - Fatal编程技术网

调用Haskell中另一个函数的内部函数

调用Haskell中另一个函数的内部函数,haskell,Haskell,我对哈斯克尔真的很陌生。我有两个元组数组函数。第一个将布尔值替换为0或1 boolToInt :: [([Char], Bool)] -> [([Char], Int)] boolToInt ((x, True):xs) = (x, 1): boolToInt xs boolToInt ((x, False):xs) = (x, 0): boolToInt xs boolToInt [] = [] Second对列表中的第二

我对哈斯克尔真的很陌生。我有两个元组数组函数。第一个将布尔值替换为0或1

boolToInt :: [([Char], Bool)] -> [([Char], Int)]
boolToInt ((x, True):xs)        = (x, 1): boolToInt xs
boolToInt ((x, False):xs)       = (x, 0): boolToInt xs
boolToInt []                    = []
Second对列表中的第二个值求和

teamNumberOfWins :: [([Char], Int)] -> Int
teamNumberOfWins  []            = 0
teamNumberOfWins ((x, y):xs)    = sum + y
   where sum = teamNumberOfWins xs
对于第二个函数,列表必须已经包含Int值。有没有办法在第一个函数中调用第二个函数?我试过这样的方法:

teamNumberOfWins :: [([Char], Int)] -> Int
teamNumberOfWins  []            = 0
teamNumberOfWins ((x, y):xs)    = sum + y
   where sum = teamNumberOfWins (boolToInt xs)
但它不起作用。有人能帮我吗?

为您辩护:

teamNumberOfWins :: [([Char], Int)] -> Int
teamNumberOfWins  []            = 0
teamNumberOfWins ((x, y):xs)    = sum + y
   where sum = teamNumberOfWins (boolToInt xs)
最后一行有问题
xs
是类型为
[([Char],Int)]
的值,但
boolToInt
仅被定义用于处理类型为
[([Char],Bool)]
的值。Haskell有一个非常严格的类型系统(这实际上是该语言的优势之一),并且不允许您这样做

您显然想要做的是获取一个类型为
[([Char],Bool)]
的列表,然后应用
boolToInt
,然后将
teamNumberOfWins
(您的原始版本)应用到结果中。这就是所谓的函数组合,Haskell有一个非常有用的内置函数/操作符来完成这项工作,它就是

因此,您只需保持前两个函数不变,然后定义一个新函数:

teamNumberOfWins' = teamNumberOfWins . boolToInt
请注意,您还可以使用
map
函数大大简化
boolToInt
的定义,该函数将一个元素的函数应用于列表中的每个元素。因此:

boolToInt = map singleBoolToInt
  where singleBoolToInt (x, True) = (x, 1)
        singleBoolToInt (x, False) = (x, 0)

如果要调用第一个函数,则输入类型应包含布尔值。另外,您不需要在每次递归调用时转换整个列表:转换一次就足够了。@chi,我应该在什么地方调用函数一次?我是这样想的,但我不知道该在哪里做。
sum[如果b那么ls中的其他0 |(|,b)]
?@seigailion-Robin下面展示了如何做:你可以定义
fys=f2(boolToInt ys)其中f2[]=;f2(x:xs)=……
。关键是,您需要定义一个辅助递归函数(
f2
)处理“带int的列表”,然后用修改后的列表调用它。请注意,您实际上不需要
boolToInt
,因为
Bool
已经有一个
Enum
实例,它允许您编写
teamNumberOfWins=((x,y):xs)=fromEnum y+teamNumberOfWins xs
,或使用Elmex80的列表理解,
sum[fromEnum b |(|,b)在我看来,为
singleBoolToInt
引入
fromEnum
是值得的。如果我们想进一步简化,我们可以让
teamNumberOfWins=length.filter snd
。但我喜欢Robin的答案,因为它向OP解释了错误,并提出了OP应该可以理解的修复方案。相比之下,只是给出了一个神秘的s像我这样的解决方案不会很有帮助,至少在OP学会一些中级Haskell之前是这样。谢谢@chi和@ATayler-我同意你的评论,我没有在
地图
之外追求简化,部分原因是懒惰和时间限制,部分原因是我自己对Haskell的熟悉程度远不如你们(当然应该发现
length.filter snd
version。)我主要想向OP展示他到底做错了什么,以及最“直接”(尽管不是“最佳”)的修复方法。