我想在haskell中编写这个函数
它是具有o(m + n)复杂度的联合函数
int printUnion(int arr1[], int arr2[], int m, int n)
{
int i = 0, j = 0;
while(i < m && j < n)
{
if(arr1[i] < arr2[j])
printf(" %d ", arr1[i++]);
else if(arr2[j] < arr1[i])
printf(" %d ", arr2[j++]);
else
{
printf(" %d ", arr2[j++]);
i++;
}
}
/* Print remaining elements of the larger array */
while(i < m)
printf(" %d ", arr1[i++]);
while(j < n)
printf(" %d ", arr2[j++]);
}
答案 0 :(得分:5)
import Control.Monad (mapM_)
编程语言之间的区别不仅在于不同的编程语言不同,而且我们使用不同的编程语言也不同。例如C和C ++是类似的编程语言,但是C程序倾向于分配一些大的内存块,而C ++程序倾向于分配更多但更小的内存块。
所以:虽然你的C函数需要两个数组(并且必须明确地传递它们的长度),但在Haskell中我们会使用列表。 (这并不是说Haskell程序从不使用数组,就像C程序从不使用列表那样,C程序倾向于使用数组而Haskell程序倾向于使用列表。)
showSpaced :: Show a => a -> String
showSpaced x = " " ++ show x ++ " "
你的C函数调用printf()
,它们都会对输出进行格式化并将其发送到stdout,但我们将分别进行这些操作。 showSpaced
适用于我们可以传递给show
的所有值。
union :: Ord a => [a] -> [a] -> [a]
union xs [] = xs
union [] ys = ys
union xs0@(x:xs1) ys0@(y:ys1) = case x `compare` y of
LT -> x : union xs1 ys0
GT -> y : union xs0 ys1
EQ -> y : union xs1 ys1
此union
函数仅需要可以比较基础元素。这两个列表必须具有相同的类型。你会注意到我们使用递归而不是循环,并且通过使用列表而不是数组,我们不必跟踪数组索引。
我们使用模式匹配,两者都给出了union
本身的三个方程式,以及case
表达式。模式匹配在Haskell中很重要:找一个解释它的教程。
printUnion :: (Ord a, Show a) => [a] -> [a] -> IO ()
printUnion xs ys = mapM_ (putStr . showSpaced) (union xs ys)
所以在printUnion
我们把它们放在一起。列表元素需要实现Ord
(我们可以调用union
)和Show
(因此我们可以调用showSpaced
),因此它们都出现在类型签名中。< / p>
当您来自C时,您可能会担心建立中间列表的效率。不要:优化器将所有内容融合到一个循环中。