我怎么能省略这个Nil案例

时间:2012-09-30 15:51:57

标签: scala sorting functional-programming

我正在使用scala实现一些常见的算法。在尝试重新创建冒泡排序时,我遇到了这个问题

这是一个内部循环的实现,它将值冒泡到顶部:

def pass(xs:List[Int]):List[Int] = xs match { 
  case Nil => Nil 
  case x::Nil => x::Nil 
  case l::r::xs if(l>r) => r::pass(l::xs)
  case l::r::xs => l::pass(r::xs)
}

我的问题是案例Nil => Nil。我知道我需要这个是因为我可以将Nil应用于此功能。有没有办法确保Nil不能以满足编译器的方式作为参数提供,以便我可以消除这种情况?

3 个答案:

答案 0 :(得分:4)

List有两个子类型,Nil和::,so ::表示至少有一个元素的列表。

def pass(xs: ::[Int]):List[Int] = xs match { 
  case x::Nil => x::Nil 
  case l::r::xs if(l>r) => r::pass(new ::(l,xs))
  case l::r::xs => l::pass(new ::(r, xs))
}

答案 1 :(得分:2)

这大致对应于原始类型的细化,您可以在其中编写一个类型,其成员是初始类型的子集。然后,您会显示,对于您的函数的每个输入xx都是非Nil。因为这需要大量证据(您可以使用子集类型在Coq中使用依赖类型实现此功能),在这种情况下更好的做法可能是引入一个新类型,这是一个list没有Nil构造函数,只有cons的构造函数和单个元素。

编辑:由于Scala允许您使用List类型的子类型来强制执行此操作,因此您可以使用该子类型在类型系统中进行可判断性证明。这是仍然一个证据,在某种意义上,任何类型检查都对应于程序确实存在某种类型的证据,它只是编译器可以完全证明的东西。

答案 2 :(得分:2)

在这种情况下,您只需使用case子句命令:

def pass(xs:List[Int]):List[Int] = xs match { 
  case l::r::xs if(l>r) => r::pass(l::xs)
  case l::r::xs => l::pass(r::xs)
  case xs => xs
}

前两个子句仅匹配具有一个或多个元素的列表。最后一个句子将在其他地方匹配。