5

私は Haskell の初心者なので、厳密な型に少し苦労しています。構築しようとしている関数で誰かが私を助けてくれるかどうか疑問に思っています。基本的に、リストのリストを取ります。次に例を示します。

[[1,2,3], [7,6,8], [0,3,4]]

それらを 1 つのリストに追加し、後のリストをそれに沿った位置の数だけ変換します。したがって、サンプルリストで作業すると、実際には次のようになります。

foldl (zipWith +) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]]

これが私の現在の関数です(型エラーを取得します):

    addLists :: [[Integer]] -> [Integer]
    addLists [[]] = []
    addLists [[x]] = [x]
    addLists [x:xs] = zipWith (+) [x] ([0]++ (addLists xs))
4

2 に答える 2

6

([0]++)は と同じであることに注意してください(0:)。これにより、見栄えが良くなり、1 つか 2 ナノ秒節約できます。(私はナノ秒のことで冗談を言っています.何かがいつナノ秒速いかを人間は知ることができませんが、とにかくこの方法の方が良いです.)

まず、必要なリストの作成について考えてみましょう。私たちは欲しい

postponeLists [[1,2,3], [7,6,8], [10,20,30,40]] 
             = [[1,2,3], [0,7,6,8], [0,0,10,20,30,40]]
             = [1,2,3] : ones that should have zero in front of them

定義には十分な情報です。

postponeLists [] = []
postponeLists (l:ls) = l : map (0:) (postponeLists ls)

今あなたは言った

foldl (zipWith +) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]]

しかし、あなたが意味する

foldl (zipWith (+)) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]]

残念ながら、リストのいずれかが要素を使い果たすとすぐに停止する[]ので、それはあなたに与えます. zipWith止まらない圧縮方法が必要です。

解決策 1: 最も長いものを見つけて、それらをすべてmaxlength使用して作成しますtake maxlength.(++ repeat 0)
。 解決策 2: 停止しない別の zipWith 関数を記述します。

私は解決策 2 を好みます。次の定義を見てみましょう。zipWith

zipWith :: (a->b->c) -> [a]->[b]->[c]
zipWith f (a:as) (b:bs) = f a b : zipWith f as bs
zipWith _ _      _      = [] -- here's the problem - it stops as soon as any list is empty

OK、それではやめましょう:

zipWithMore :: (a -> a -> a) -> [a] -> [a] -> [a]
zipWithMore f (a:as) (b:bs) = f a b : zipWithMore f as bs
zipWithMore f []      bs      = bs -- if there's more in bs, use that
zipWithMore f as      []      = as -- if there's more in as, use that

と交換できるようにzipWith (+)なりましたzipWithMore (+)。オチはお任せします。

于 2012-10-31T12:21:07.943 に答える
3

これはあなたが望むことだと思います

import Data.List (transpose)

addLists :: Num a => [[a]] -> [a]
addLists xs = map sum . transpose $ zipWith (\n x -> replicate n 0 ++ x) [0..] xs
于 2012-10-31T12:14:21.730 に答える