在Haskell列表列表中找到最短的列表

时间:2018-10-30 15:50:44

标签: haskell recursion minimum type-mismatch

我使用Haskell编写的程序遇到一些困难。其背后的思想是递归地在列表列表中找到最短的列表,然后返回该列表。我已经设法编写了程序,但似乎无法弄清楚我在程序中做错了什么。这些是我尝试进行编译时遇到的错误:

  • 无法将类型“ a”与“ [[[a]]””匹配,“ a”是受类型签名约束的刚性类型变量,用于:shortest :: forall a。 [[a]]-> [a]最短。hs:1:13。预期类型:[[[a]]],实际类型:[a]
  • 在“最短”的第一个参数中,即“ y”。在“(:)”的第一个参数中,即“最短y”。在表达式中:最短y:[列表]
  • 相关绑定包括列表:: [[a]](以shortest.hs:4:15绑定),y :: [a](以shortest.hs:4:13绑定),x :: [a] (以shortest.hs:4:11绑定),最短::: [[a]]-> [a](以shortest.hs:2:1绑定)。

这是我正在使用的代码:

shortest :: [[a]] -> [a]
shortest [] = []
shortest [y] = y
shortest (x:y:list)
   | length x > length y = shortest y:[list]
   | otherwise = shortest x:[list]

如果有人能给我有关我要去哪里的任何指示,将不胜感激!

4 个答案:

答案 0 :(得分:5)

list已经是您输入内容的结尾;您不需要(也不应该)将其包装在另一个列表中。

shortest (x:y:list) = shortest $ (if length x > length y then y else x) : list

在每个步骤中,仅是从递归调用的输入中删除哪个元素xy的问题。

另一种方法(不需要两个基本情况)是将列表的开头与结尾的递归结果进行比较。

shortest [] = []
shortest (x:xs) = let s = shortest xs
                  in if length s < length x then s else x

最后,元组在字典上进行比较,因此,您还可以通过以下方式省去显式递归:标记每个列表的长度,找到最小的标记值,然后提取原始列表。

shortest = snd . minimum . map (\x -> (length x, x))

使用Control.Arrow,您可以将参数写为map(length &&& id)

最后一种方法的注意事项:由于列表也按字典顺序进行比较,因此,如果您有多个长度最短的列表,则最终结果将取决于列表值自身的比较方式。相比之下,前两个示例是稳定的。将返回第一个这样的最短列表。


Daniel Wagner指出了使用minimum的更好解决方案,该解决方案是将每个元素包装在一个Arg值中,该值可以仅对两个列表的长度进行比较,而不考虑列表的内容。

import Data.Semigroup
shortest xs = x where Arg _ x = minimum [Arg (length x) x | x <- xs]

Arg基本上是一种2元素产品类型,仅{em> 对其Ord实例使用第一个元素,而(,)不使用这两个元素。

>

答案 1 :(得分:4)

  shortest []=[]
  shortest [y] = y
  shortest (x:y:list)
   |length x > length y = shortest (y:list)            
   |otherwise = shortest (x:list)

这有效:),也值得一提的是,如果列表中有2个或多个“最短”元素,则第一个元素将始终弹出。

   Prelude>shortest[[1],[2],[3]]
   [1]

答案 2 :(得分:3)

registerProcessor('noise-generator',class extends AudioWorkletProcessor {
  process(inputs, outputs) {
    for (let i=0;i<outputs[0][0].length;++i)  outputs[0][0][i]=2*Math.random()-1;
    return true;
  }
});

registerProcessor('gain-processor',class extends AudioWorkletProcessor {
  // Custom AudioParams can be defined with this static getter.
  static get parameterDescriptors() { return [{name:'gain',defaultValue:0.1}] }
//  constructor() { super() }  // The super constructor call is required
  process(inputs, outputs, parameters) {
    const input = inputs[0],output = outputs[0];
    for (let channel=0;channel<inputs[0].length;++channel)
      for (let i=0;i<input[channel].length;++i) output[channel][i] = input[channel][i] * parameters.gain[0];
    return true;
  }
});

registerProcessor('lowpass-filter', class extends AudioWorkletProcessor {
  static get parameterDescriptors() { return [{name:'frequency',defaultValue:1000,minValue:0}]; }
  constructor() {
    super();
    this.lastOut = 0;
  }
  process(inputs, outputs, parameters) {
    let input = inputs[0],output = outputs[0],coeff;
    let frequency = parameters.frequency;
    for (let channel = 0; channel < output.length; ++channel) {
      let inputChannel = input[channel],outputChannel = output[channel];
      coeff = 2 * Math.PI * frequency[0] / sampleRate;
      for (let i = 0; i < outputChannel.length; ++i) {
        outputChannel[i]=inputChannel[i] * coeff +(1-coeff)*this.lastOut;
        this.lastOut=outputChannel[i];
      }
    }
    return true;
  }
});

无积分:

import Data.List
import Data.Ord
shortest list = minimumBy (comparing length) list

这些库包含在GHC中。他们的名字说他们做得很好。也许在单独的情况下添加空列表。

答案 3 :(得分:2)

我认为您只需要括号:shortest (y:list),对于x情况也是这样。

:的优先级使其看起来像(shortest y) : list