在 Haskell 中有没有办法使用“<=”进行模式匹配?
Is there a way to use "<=" for pattern matching in Haskell?
我有以下代码,它删除列表中的第 n 个元素。
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = f xs n ++ dropEvery (drop n xs) n
where
f ys 0 = []
f ys 1 = []
f [] m = []
f (y:ys) n = y : (f ys (n-1))
我想让它短一点,想知道是否有办法在模式匹配中使用“<=”。我尝试使用 where
子句来执行此操作,但是没有用,为什么?
f ys m = []
where
m <= 1 || ys == []
我怎样才能避免这种冗余?在模式匹配中有没有使用“小于或等于”的好方法?
编辑:我用守卫试过了
where
f ys m
| m <= 1 || null ys = []
| otherwise = (head ys) : (f (tail ys) (n-1))
你可以和守卫一起工作:
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = f xs n ++ dropEvery (drop n xs) n
where
f ys i <b>| i <= 1</b> = []
f [] _ = []
f (y:ys) n = y : (f ys (n-1))
如果守卫中的条件得到满足,则该子句“触发”,因此在这种情况下将 return 一个空列表 []
。
但是你会陷入无限循环,因为你写 f xs n ++ <b>dropEvery (n xs) n</b>
但是drop 3 []
将 return []
,因此它将继续使用空列表调用 dropEvery
。
你可以利用递归,我们每次递减 n
直到它达到 0
,然后我们进行两次跳跃,所以:
dropEvery :: Int -> [a] -> [a]
dropEvery n = go (n-1)
where go _ [] = []
go i (x:xs)
| <b>i <= 0</b> = go (n-1) xs
| otherwise = x : go (i-1) xs
我们还可以使用 splitAt :: [a] -> ([a], [a])
和 模式守卫:
dropEvery n [] = []
dropEvery n ds
| <b>(_:ys) <- sb</b> = sa ++ dropEvery n ys
| otherwise = sa
where (sa, sb) = splitAt (n-1) ds
我有以下代码,它删除列表中的第 n 个元素。
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = f xs n ++ dropEvery (drop n xs) n
where
f ys 0 = []
f ys 1 = []
f [] m = []
f (y:ys) n = y : (f ys (n-1))
我想让它短一点,想知道是否有办法在模式匹配中使用“<=”。我尝试使用 where
子句来执行此操作,但是没有用,为什么?
f ys m = []
where
m <= 1 || ys == []
我怎样才能避免这种冗余?在模式匹配中有没有使用“小于或等于”的好方法?
编辑:我用守卫试过了
where
f ys m
| m <= 1 || null ys = []
| otherwise = (head ys) : (f (tail ys) (n-1))
你可以和守卫一起工作:
dropEvery :: [a] -> Int -> [a]
dropEvery xs n = f xs n ++ dropEvery (drop n xs) n
where
f ys i <b>| i <= 1</b> = []
f [] _ = []
f (y:ys) n = y : (f ys (n-1))
如果守卫中的条件得到满足,则该子句“触发”,因此在这种情况下将 return 一个空列表 []
。
但是你会陷入无限循环,因为你写 f xs n ++ <b>dropEvery (n xs) n</b>
但是drop 3 []
将 return []
,因此它将继续使用空列表调用 dropEvery
。
你可以利用递归,我们每次递减 n
直到它达到 0
,然后我们进行两次跳跃,所以:
dropEvery :: Int -> [a] -> [a]
dropEvery n = go (n-1)
where go _ [] = []
go i (x:xs)
| <b>i <= 0</b> = go (n-1) xs
| otherwise = x : go (i-1) xs
我们还可以使用 splitAt :: [a] -> ([a], [a])
和 模式守卫:
dropEvery n [] = []
dropEvery n ds
| <b>(_:ys) <- sb</b> = sa ++ dropEvery n ys
| otherwise = sa
where (sa, sb) = splitAt (n-1) ds