我迈出了第一步,进入了Haskell的精彩世界。作为练习,我想实现一个方法,它找到列表的最大元素及其索引。我们称这个函数为“maxi”。在列表上调用maxi应该返回以下结果:
ghci> maxi [1, 3, 4, 1, 2, 3]
(4, 2)
4是此列表中的最大int,它位于索引2。
我试图按如下方式实现此功能:
maxim :: (Ord a) => [a] -> (a, Int)
maxim l =
let pmaxim :: (Ord a) => [a] -> Int -> (a, Int) -- Internal function to do the work
pmaxim [] _ = error "Empty list" -- List is empty, error
pmaxim [x] xi = (x, xi) -- List has one item, return it and the index
pmaxim (x:xs) xi -- More than one item, break list apart
| x > t = (x, xi) -- If current item is bigger, return it and its index
| otherwise = (t, ti) -- If list tail has a bigger item, return that
where (t, ti) = pmaxim xs (ti + 1) -- Get max of tail of the list
in pmaxim l 0 -- Call internal function with start index
当我这样称呼时,我得到一些非常奇怪的东西:ghci似乎在返回max element的值后挂起。
ghci> maxi [1, 3, 4, 1, 2, 3]
(4,
我猜想这与Haskell的懒惰评估性质有关,但我发现很难弄清楚这里究竟发生了什么,以及如何解决它。我也非常感谢任何人可能有关如何在Haskell中调试的提示。是否有一种简单的方法可以在执行期间打印输出值而不影响行为?
我只想指出,我知道有几种更好的方法可以使用内置的Haskell函数来获得这种行为。我从头开始实现这个,试着学习Haskell。
谢谢
答案 0 :(得分:20)
这是因为您的代码中存在轻微错误。你有:
where (t, ti) = pmaxim xs (ti + 1)
......但实际应该是:
where (t, ti) = pmaxim xs (xi + 1)
这会修复您的代码,现在可以生成正确的解决方案:
>>> maxim [1, 2, 3, 2, 1]
(3, 2)
您的代码被绞死是因为您对ti
的计算导致无限循环,因为您不小心根据自身定义了它。请注意,ghc
是一个足够智能的编译器,并且发现t
不依赖于ti
的值,这就是为什么您的版本仍可以成功计算最大值,即使它不能计算指数。
调试纯计算的标准方法是Debug.Trace
模块。
作为旁注,有一个更简单的解决方案:
import Data.List
import Data.Ord
maxi xs = maximumBy (comparing fst) (zip xs [0..])
编辑:糟糕,我没有看到你是故意从头开始实施它,但我仍然会留在那里。
答案 1 :(得分:0)
我看到您已经回答了您的问题。我使用lambda函数设法做到了无需递归。
Asett=[
"A" ,
"B",
"C"
]
var Bset = [
"D",
"E",
"F"
];
var Cset = [
"G" ,
"H",
"I"
];
var Dset = [
"J",
"K",
"L"
];
var cSets = [];
var vSets=[];
var dSets=[];
var fSets=[];
function initiate(){ //this function initiates the given arrays with defined elements and value equal to 10
for (var iv=0;iv<3;iv++){
cSets.push({
key: Asett[iv],
rem:10
})
}
for (var iv=0;iv<3;iv++){
vSets.push({
key: Bset[iv],
rem:10
})
}
for (var iv=0;iv<3;iv++){
dSets.push({
key: Cset[iv],
rem:10
})
}
for (var iv=0;iv<3;iv++){
fSets.push({
key: Dset[iv],
rem:10
})
}
}
initiate();
generateList(cSets,vSets,dSets,fSets);
function generateList(cSets,vSets,dSets,fSets){
var j=0;
var k=0;
var l=0;
var m=0;
var taskL = []; // create an empty array
var f=0;
for (var i=0; i<27;i++){
j=getRndInteger(0,2);
k=getRndInteger(0,2);
l=getRndInteger(0,2);
m=getRndInteger(0,2);
var combinations="";
while (cSets[j].rem<=0) // I get cSets[j] undefined error
{
j=(j % 3) +1;
}
combinations+=comSets[j].key+",";
comSets[j].rem--;
while (vSets[k].rem<=0) //I get vSets[k] undefined error
{
k=(k % 3) +1;
}
combinations+=vSets[k].key+",";
vSets[k].rem--;
while (dSets[l].rem<=0) //I get dSets[l] undefined error
{
l=(l % 3) +1;
}
combinations+=changeSets[l].key+",";
changeSets[l].rem--;
while (fSets[m].rem<=0) //I get fSets[m] undefined error
{
m=(m % 3) +1;
}
combinations+=fSets[m].key+",";
fSets[m].rem--;
taskL[f++]=combinations;
}
}