假设我输入以下内容:
[(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]) ...]
答案 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 =<<)
。