簡體   English   中英

將鄰接表轉換為元組數組Haskell

[英]Turn adjacency list into tuple array Haskell

假設我輸入以下內容:

[(0, [1, 2]) , (2, [3, 4]) , (4, [])

這是一個鄰接表,我想這樣轉換它:

[(0,1), (0,2), (2,3), (2, 4)] -注意沒有4映射到任何東西

這是我到目前為止的內容:

conv :: [(Int, [Int])] -> [(Int, Int)]

conv adj = map fn adj -- mapping (0, [1, 2]) should give me [(0, 1), (0, 2)]

fn:: (Int, [Int]) -> [(Int, Int)]

fn (rt, list) = -- somehow perform [(rt, l[0]), (rt, l[1]) ...]

列表理解可以解決問題:

conv :: [(a, [b])] -> [(a, b)]
conv xys = [(x, y) | (x, ys) <- xys, y <- ys ]

或者我們可以在這里使用concatMap

conv :: Foldable f => f (a, [b]) -> [(a, b)]
conv = concatMap (uncurry (map . (,)))

在這里,內部函數uncurry (map . (,))取一個元組(x, ys) ,從而執行一個map (x,)uncurry基本上將其元組(x, ys) uncurry ,然后調用(map . (,)) x ys ,這意味着我們獲得(map (x,)) ys 上面的語法使用了TupleSections擴展,但是我們不需要在實際程序中激活該擴展,因為我們從不編寫這種語法。 因此,您定義的fn函數等效於uncurry (map . (,))

因此,我們在concatMap中使用此函數,該concatMap將傳遞2個元組,並連接這些單個元組創建的列表。

或者我們可以使用“ bind” >>= :: Monad m => ma -> (a -> mb) -> mb函數:

conv :: Monad m => m (a, m b) -> m (a, b)
conv = (=<<) (\(x, ys) -> ys >>= return . (x,))

或更短:

conv :: Monad m => m (a, m b) -> m (a, b)
conv = (=<<) (uncurry (fmap . (,)))

后者的好處是它也可以與Maybe等等一起使用,例如:

Prelude> conv [(0, [1, 2]) , (2, [3, 4]) , (4, [])]
[(0,1),(0,2),(2,3),(2,4)]
Prelude> conv Nothing
Nothing
Prelude> conv (Just (3, Nothing))
Nothing
Prelude> conv (Just (3, Just 2))
Just (3,2)

利用instance Traversable ((,) a)instance Traversable ((,) a) ,我們得到了一個非常短的(而且非常難懂的)解決方案:

conv :: [(Int, [Int])] -> [(Int, Int)]
conv = (sequence =<<)

(sequence =<<)的最一般類型是(Monad m, Traversable t) => m (t (ma)) -> m (ta)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM