将c ++代码转换为haskell

时间:2012-11-20 01:44:19

标签: haskell

我想在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++]);
}

1 个答案:

答案 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时,您可能会担心建立中间列表的效率。不要:优化器将所有内容融合到一个循环中。