我对学习如何在Haskell中编程非常陌生。
我有一个方法positions
的示例:
positions :: Eq a => a -> [a] -> [Int]
positions x xs = [i | (y, i) <- zip xs [0..], y == x]
我的目标是找到一种定义positions
函数的方法,但要使用find
方法。
find
方法:
find :: Eq a => a -> [(a,b)] -> [b]
find k t = [v | (m, v) <- t, m == k]
有人可以解释仅使用 positions
函数来声明find
函数的方法吗?
我不明白如何使用find
函数跟踪索引。
答案 0 :(得分:2)
我们首先将positions
重写为
positions x xs = map (\(_, i) -> i) . filter (\(y, _) -> y == x) $ zip xs [0..]
然后我们将find
重新写为
find k t = map (\(_, v) -> v) . filter (\(m, _) -> m == k) $ t
-- or,
find x = map (\(_, i) -> i) . filter (\(y, _) -> y == x)
,然后简单地注意到这两段代码完全相同(在重命名变量之后):
positions x xs = find x $ zip xs [0..]
find
仅接受对的列表,然后过滤它们并提取第二个成分;您将必须使用 something (例如 zip
)来生成find
要处理的对。 没有解决方法。
当然,positions
也可以不用zip
部分进行编码(而不是使用mapAccumL
进行编码),但是它不需要find
:
-- mapAccumL :: (acc -> x -> (acc, y)) -> acc -> [x] -> (acc, [y])
positions :: (Eq a) => a -> [a] -> [Int]
positions x = concat . snd . mapAccumL g 0
where
g acc y = (acc+1, [acc | y == x])
我们可以使它人为地产生find
所期望的列表,但是它将重做很多工作,并且只是对zip
的枚举部分的重新实现(因此,而不是find
本身。
答案 1 :(得分:2)
看:
positions x xs = [i | (y, i) <- zip xs [0..], y == x]
find k t = [v | (m, v) <- t , m == k]
它们看起来很相似!通过在实现的过程中将k
重命名为x
,将m
重命名为y
,将v
重命名为i
,我们可以使其更加引人注目。 find
:
positions x xs = [i | (y, i) <- zip xs [0..], y == x]
find x t = [i | (y, i) <- t , y == x]
所以现在很明显:我们要做的就是让positions
传递zip xs [0..]
作为t
的{{1}}参数。
find