Haskell 哈斯克尔:最小位置
我是哈斯克尔术语的初学者。我必须做一个显示所有最小位置的练习。 例如:[1,2,3,1,1]=>0,3,4这些是最小位置。 我试着用两种方法来做这件事,但都不管用。 有人能帮我做一个递归版本吗 第一:Haskell 哈斯克尔:最小位置,haskell,Haskell,我是哈斯克尔术语的初学者。我必须做一个显示所有最小位置的练习。 例如:[1,2,3,1,1]=>0,3,4这些是最小位置。 我试着用两种方法来做这件事,但都不管用。 有人能帮我做一个递归版本吗 第一: findPos :: [Int]->Int->[Int] findPos list minimum (list) = [index | (index, e) <- zip [0..] list, e == minimum (list)] findPos::[Int]->Int-
findPos :: [Int]->Int->[Int]
findPos list minimum (list) = [index | (index, e) <- zip [0..] list, e == minimum (list)]
findPos::[Int]->Int->[Int]
findPos列表最小值(list)=[index |(index,e)Int->[Int]
findPos列表(最小el)=[index |(index,e)Int
最小x=如果(尾部(x)=[]),则头部(x)
其他
其中n=最小值(尾部(x))
n=如果n
您的代码有问题
这完全是错误的。您稍后会找到最小值(使用最小值列表
);不需要传递它:
findPos :: [Int] -> [Int]
findPos list = ...
我的解决方案
不是递归的,但我个人会这么做
我非常喜欢拉链解决方案,我不知道你为什么选择理解
[0..]
压缩数据snd
等于最小元素筛选出数据fst
剧透
代码的严重问题是函数定义的左边有一些奇怪的东西 在第一种情况下,您有:
findPos :: [Int] -> Int-> [Int]
findPos list minimum (list) = …
这意味着什么?根据您给findPos
的签名判断,它包含一个列表和我们正在寻找的元素。因此定义必须是:
findPos list m = [index | (index, e) <- zip [0..] list, e == m]
或您可以将定义更改为:
findPos :: [Int] -> [Int]
findPos list = [index | (index, e) <- zip [0..] list, e == minim list]
<> P> >您的<代码> MIIM几乎是正确的,除了定义了<代码> N< /代码>两次。 < P>作为早期答案的一个变体,让我们考虑一个解决方案,在这里我们准确地访问输入列表的每一个元素。就像前面的答案,这不是一个明确的递归解决方案,而是使用递归函数<代码>foldr
-- | Accumulate function
--
acc :: Ord a => (t, a) -> ([t], a) -> ([t], a)
acc (i, x) z@(is, y) = case compare x y of
LT -> ([i], x) -- a new minimum! reinit the list of mins
EQ -> (i:is, y) -- equal minimum; add to the list of mins
_ -> z -- larger than min; accumulator unchanged
findPos = (Bounded a, Ord a) => [a] -> [Int]
findPos = fst . foldr acc ([], maxBound) . zip [(0 :: Int)..]
因此,我们用数字列表zip
标记(从零开始计数),将累加器初始化为([],maxBound)
(初始最小值是可能的最大值),然后提取输入中最小值的索引列表
为了消除Bounded
类型类约束(因此findPos
可以与Integer
或其他无界有序类型一起工作),可以应用Maybe
类型构造函数,我将其留作练习
跟踪“看到的最小值”以及看到该值的索引,可以构建一个流处理机器,您可以随时询问“到目前为止(可能无限)输入流中最小值的索引是什么。”只有一个小细节:在OP中,索引从
0开始,因此无限索引列表必须是[0..]
。
findPos list m = [index | (index, e) <- zip [0..] list, e == m]
findPos' :: [Int] -> [Int]
findPos' list = findPos list (minim list)
findPos :: [Int] -> [Int]
findPos list = [index | (index, e) <- zip [0..] list, e == minim list]
minim :: [Int] -> Int
minim (x : []) = x
minim (x : xs) = if x < m then x else m
where
m = minim xs
-- | Accumulate function
--
acc :: Ord a => (t, a) -> ([t], a) -> ([t], a)
acc (i, x) z@(is, y) = case compare x y of
LT -> ([i], x) -- a new minimum! reinit the list of mins
EQ -> (i:is, y) -- equal minimum; add to the list of mins
_ -> z -- larger than min; accumulator unchanged
findPos = (Bounded a, Ord a) => [a] -> [Int]
findPos = fst . foldr acc ([], maxBound) . zip [(0 :: Int)..]