2013-06-03 8 views
7

Ich möchte eine Liste von Verkettungen in Haskell machen. Ich habe [1,2,3] und [4,5,6] und möchte [14,15,16,24,25,26,34,35,36] produzieren. Ich weiß, ich zipWith oder etw verwenden kann, aber wie äquivalent zu tun: second_arrayNested loop äquivalent

Ich glaube, ich habe verwenden Karte und die Hälfte curried Funktionen, kann aber nicht wirklich in allein foreach in first_array foreach machen: S

Antwort

17

Sie Liste Verständnis verwenden könnte, es zu tun:

[x * 10 + y | x <- [1..3], y <- [4..6]] 

In der Tat ist dies eine direkte Übersetzung einer verschachtelten Schleife, da die erste der Außen/langsamer Index ist, und das zweite ist die schneller/innerer Index.

12

Sie können die Tatsache ausnutzen, dass die Listen sind Monaden und verwenden Sie die Notation tun:

do 
    a <- [1, 2, 3] 
    b <- [4, 5, 6] 
    return $ a * 10 + b 

Sie können auch nutzen die Tatsache aus, dass die Listen sind applicative functors (vorausgesetzt, Sie haben Control.Applicative importiert):

(+) <$> (*10) <$> [1,2,3] <*> [4,5,6] 

Beides führt im folgenden:

[14,15,16,24,25,26,34,35,36] 
5

Wenn Sie wirklich for in Ihrem Code wie sehen Sie auch so etwas tun können:

for :: [a] -> (a -> b) -> [b] 
for = flip map 

nested :: [Integer] 
nested = concat nested_list 
    where nested_list = 
      for [1, 2, 3] (\i -> 
      for [4, 5, 6] (\j -> 
       i * 10 + j 
      ) 
     ) 

Sie auch in for und Identity für einen idiomatischen Ansatz aussehen könnten.

1

Verschachtelte Schleifen entsprechen verschachtelten Verwendungen von map oder ähnlichen Funktionen. Erste Annäherung:

notThereYet :: [[Integer]] 
notThereYet = map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3] 

Das gibt Ihnen verschachtelte Listen, die Sie auf zwei Arten beseitigen können. Eine davon ist die concat :: [[a]] -> [a] Funktion zu verwenden:

solution1 :: [Integer] 
solution1 = concat (map (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3]) 

Ein weiterer Grund ist diese eingebaute Funktion zu verwenden:

concatMap :: (a -> [b]) -> [a] -> [b] 
concatMap f xs = concat (map f xs) 

verwenden, die:

solution2 :: [Integer] 
solution2 = concatMap (\x -> map (\y -> x*10 + y) [4, 5, 6]) [1, 2, 3] 

Andere Leute haben erwähnt Listenkomprehensionen und die Liste Monade, aber diese wirklich unten genisteten Verwendungen von concatMap.

0

Die allgemeine Lösung der Verkettung von zwei Listen von ganzen Zahlen ist diese:

concatInt [] xs = xs 
concatInt xs [] = xs 
concatInt xs ys = [join x y | x <- xs , y <- ys ] 
    where 
    join x y = firstPart + secondPart 
     where 
     firstPart = x * 10^lengthSecondPart 
     lengthSecondPart = 1 + (truncate $ logBase 10 (fromIntegral y)) 
     secondPart = y 

Beispiel: concatInt [1,2,3] [4,5,6] == [14,15,16 , 24,25,26,34,35,36]

Komplexeres Beispiel: concatInt [0,2,10,1,100,200] [24,2,999,44,3] == [24,2,999,44, 3,224,22,2999,244,23,1024,102,1999,110,100,124,12,1999,144,13,10024,1002,100999,10044,1003,20024,200,2009999,20044,2003]

1

WeilDie 10 Notation und das Listenverständnis wurden bereits erwähnt. Die einzige andere Option, die ich kenne, ist über den liftM2 Kombinator von Control.Monad. Das ist genau dasselbe wie die vorherigen zwei.

liftM2 (\a b -> a * 10 + b) [1..3] [4..6] 
+0

... nur kürzer (als alle außer dem ersten). :) NICCCCE! –