2017-12-19 1 views
1

Ich übe einige Haskell Prüfung Papier Fragen und haben über die folgendenHaskell - Weben Sie zwei Listen in Blöcken der Größe n zusammen?

definieren eine Haskell-Funktion weaveHunks kommen, die einen int und zwei Listen nimmt und webt sie zusammen in große Stücke der angegebenen Größe. Achten Sie darauf, seine Typ-Signatur zu deklarieren.

Beispiel:

weaveHunks 3 "abcdefghijklmno" "ABCDEFGHIJKLMNO"

=> "abcABCdefDEFghiGHIjklJKLmnoMNO"

ich folgend auf Stack-Überlauf gefunden habe, die einfach zu zwei Listen verweben, sondern nur in Stücke von 1

weaveHunks :: [a] -> [a] -> [a] 
weaveHunks xs [] = xs 
weaveHunks [] ys = ys 
weaveHunks (x:xs) (y:ys) = x : y : weaveHunks xs ys 

ich Probleme habe Anpassung dieser Stücke fo n Größe zu nehmen, bin ich sehr neu in Haskell aber thi s ist das, was ich bisher

weaveHunks :: Int -> [a] -> [a] -> [a] 
weaveHunks n xs [] = xs 
weaveHunks n [] ys = ys 
weaveHunks n xs ys = (take n xs) : (take n ys) : weaveHunks n (drop n xs) (drop n ys) 

Ich erhalte einen Fehler in der letzten Zeile

(Typ konnte nicht übereinstimmen a' with [a] ')

Ist (drop n xs) nicht eine Liste?

+0

Die Art von 'weaveHunks' sagt, dass es ein' [a] 'produziert. Wenn Sie die Typensignatur weglassen und diese in ghci laden, was sagt Ihnen dann der Typ? – dfeuer

+0

Ich entfernte die Typ-Signatur und: t gab mir 'webenHunks :: p -> [a] -> [a] -> [a]' –

+0

Oh, Entschuldigung, ich habe etwas verpasst; Sie müssen die ersten beiden Zeilen löschen, um diese Art von Informationen zu erhalten. Wie auch immer, du hast deine Antwort bekommen. – dfeuer

Antwort

2

Sie sind sehr nah dran!

die : Betreiber Durch die Verwendung des hunks Zierer Sie zum Ausdruck, dass take n xs ein Element der Ergebnisliste ist, take n ys die nächste, und so weiter. Aber in beiden Fällen ist es mehrere Elemente, die Sie vor. Das ist die [a], die eigentlich nur a sein sollte.

Die Lösung besteht darin, stattdessen den Operator ++ zu verwenden, der eine ganze Liste und nicht nur ein einzelnes Element vorsieht.

Dies ist die vollständige Lösung, wie ich es schreiben würde:

weaveHunks :: Int -> [a] -> [a] -> [a] 
weaveHunks _ xs [] = xs 
weaveHunks _ [] ys = ys 
weaveHunks n xs ys = xHunk ++ yHunk ++ weaveHunks n xRemain yRemain 
where [(xHunk, xRemain), (yHunk, yRemain)] = splitAt n <$> [xs,ys] 
+0

Ah, ich sehe, danke. Kann ich auch fragen, was bedeutet <$>? –

+0

Es ist fmap, aber als Infix-Operator. Für Listen, fmap = map aus historischen Gründen. – HTNW

+0

Okay, danke. –

1

Wie @leftaroundabout sagte, da Ihre Anhänge Listen vom Typ [a], müssen Sie ++ statt : verwenden. In diesem Sinne wäre der Code dann wie folgt aussehen:

weaveHunks :: Int -> [a] -> [a] -> [a] 
weaveHunks _ xs [] = xs 
weaveHunks _ [] ys = ys 
weaveHunks n xs ys = (take n xs) ++ (take n ys) ++ weaveHunks n (drop n xs) (drop n ys) 

Wenn Ihr Interesse, Sie auch Bibliotheksfunktionen verwenden können, um diese Aufgabe zu tun:

import Data.List.Split 

weaveHunks :: Int -> [a] -> [a] -> [a] 
weaveHunks n xs ys = concat $ zipWith (++) (chunksOf n xs) (chunksOf n ys) 

Hinweis:chunksOf ist von Data.List.Split , die die Liste in Unterlisten der Länge n aufteilt, so ist der Typ dieser Funktion Int -> [a] -> [[a]]. zipWith Zips zwei Listen basierend auf einer Bedingung, in diesem Fall Verkettung ++. concat verwandelt eine Liste von [[a]] in [a].

+1

haben Sie Ihre 2. Lösung mit zwei Listen von radikal verschiedenen Größen getestet? Zip neigt dazu, einen baumelnden Schwanz bei Größenabweichungen abzuschneiden. –

Verwandte Themen