将邻接表转换为元组数组Haskell

时间:2019-02-12 20:02:54

标签: list 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]) ...]

2 个答案:

答案 0 :(得分:2)

列表理解可以解决问题:

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)拆包,并调用{{ 1}},这意味着我们获得了(map . (,)) x ys。上面的语法使用(map (x,)) ys扩展名,但是我们不需要在实际程序中激活该扩展名,因为我们从不编写这种语法。因此,您定义的TupleSections函数等效于fn

因此,我们在uncurry (map . (,))中使用此函数,该函数将传递2个元组,并连接这些单个元组创建的列表。

或者我们可以使用“ bind” >>= :: Monad m => m a -> (a -> m b) -> m b函数:

concatMap

或更短:

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

答案 1 :(得分:2)

利用handleRoute('/users/:userID', (req, res) => { const { userID } = req.params; const idIsValid = validateUserID(userID); if (!idIsValid) { return res.status(400).send('Invalid user ID!'); } ... }); 的优势,我们提供了一种非常简短(而且非常难以理解)的解决方案:

instance Traversable ((,) a)

conv :: [(Int, [Int])] -> [(Int, Int)] conv = (sequence =<<) 的最一般类型是(sequence =<<)