我正在尝试自学Haskell(来自OOP语言)。很难掌握不可变变量的东西。我正在尝试在行专业中对二维数组进行排序。
在java中,例如(伪):
int array[3][3] = **initialize array here
for(i = 0; i<3; i++)
for(j = 0; j<3; j++)
if(array[i][j] < current_low)
current_low = array[i][j]
如何在Haskell中实现同样的东西?如果我创建一个临时数组以在每次迭代后添加低值,我将无法添加它,因为它是不可变的,对吗?另外,Haskell没有循环,对吧?
这是我在Haskell中所知道的一些有用的东西:
main = do
let a = [[10,4],[6,10],[5,2]] --assign random numbers
print (a !! 0 !! 1) --will print a[0][1] in java notation
--How can we loop through the values?
答案 0 :(得分:2)
首先,您的Java代码不对任何内容进行排序。它只找到最小的元素。而且,有一种明显的Haskell解决方案......猜猜看,该函数被称为minimum
!让我们看看它的作用:
GHCI&GT; :t最小
minimum :: Ord a =&gt; [a] - &gt;一个
好的,所以它需要一个可以比较的值列表(因此Ord
)并输出一个值,即最小值。我们如何将其应用于“2D列表”(嵌套列表)?嗯,基本上我们需要在子列表的所有最小值中的最小值。所以我们首先用最小值列表替换列表列表
allMinima = map minimum a
...然后使用minimum allMinima
。
写得紧凑:
main :: IO ()
main = do
let a = [[10,4],[6,10],[5,2]] -- don't forget the indentation
print (minimum $ map minimum a)
这就是全部!
确实,“循环通过价值观”是一个非常缺乏功能的概念。我们通常不想谈论需要采取的单个步骤,而是考虑我们想要的结果的属性,并让编译器弄清楚如何做它。因此,如果我们不被允许使用预定义的minimum
,请按照以下方式进行思考:
如果我们有一个列表并查看单个值...在什么情况下它是正确的结果?好吧,如果它小于所有其他值。其他值中最小的是什么?确切地说,它们中的最小值。
minimum' :: Ord a => [a] -> a
minimum' (x:xs)
| x < minimum' xs = x
如果它不小,那么我们只使用其他值的最小值
minimum' (x:xs)
| x < minxs = x
| otherwise = minxs
where minxs = minimum' xs
还有一件事:如果我们通过这种方式递归列表,那么在某些时候将没有第一个元素可以与某些东西进行比较。为了防止这种情况,我们首先需要单个元素列表的特殊情况:
minimum' :: Ord a => [a] -> a
minimum' [x] = x -- obviously smallest, since there's no other element.
minimum' (x:xs)
| x < minxs = x
| otherwise = minxs
where minxs = minimum' xs
答案 1 :(得分:1)
minimum
的定义。
flatten :: [[a]] -> [a]
flatten [] = []
flatten xs = foldr (++) [] xs
squarize :: Int -> [a] -> [[a]]
squarize _ [] = []
squarize len xs = (take len xs) : (squarize len $ drop len xs)
crappySort :: Ord a => [a] -> [a]
crappySort [] = []
crappySort xs =
let smallest = minimum xs
rest = filter (smallest /=) xs
count = (length xs) - (length rest)
in
replicate count smallest ++ crappySort rest
sortByThrees xs = squarize 3 $ crappySort $ flatten xs