Haskell提供typed holes。
示例:
f :: Int -> String -> Bool
f x y = if (x > 10) then True else (g y)
g :: String -> Bool
g s = _
汇编:
Prelude> :l HoleEx.hs
[1 of 1] Compiling Main ( HoleEx.hs, interpreted )
HoleEx.hs:6:7:
Found hole `_' with type: Bool
Relevant bindings include
s :: String (bound at HoleEx.hs:6:3)
g :: String -> Bool (bound at HoleEx.hs:6:1)
In the expression: _
In an equation for `g': g s = _
Failed, modules loaded: none.
在Scala中编程时,我通常使用???
作为我尚未编写的Scala代码中的占位符。
但是,对我来说,使用打字孔似乎更有用。请注意,我可以将else (g y)
替换为else (g 55)
,但我会收到编译时错误:
Prelude> :l HoleEx.hs
[1 of 1] Compiling Main ( HoleEx.hs, interpreted )
HoleEx.hs:3:39:
Couldn't match type `Int' with `[Char]'
Expected type: String
Actual type: Int
In the first argument of `g', namely `x'
In the expression: (g x)
Failed, modules loaded: none.
虽然我可以在Scala中使用???
来获取占位符实现来编译,但与洞不同,我会在???
时遇到运行时错误。
scala> def g(x: Int): Int = ???
g: (x: Int)Int
scala> g(5)
scala.NotImplementedError: an implementation is missing
Scala是否有打孔?
答案 0 :(得分:3)
Scala的30
只是抛出异常的简写,相当于Haskell的int columnCount = 4;
int rowCount = 13;
this.tableLayoutPanel1.ColumnCount = columnCount;
this.tableLayoutPanel1.RowCount = rowCount;
this.tableLayoutPanel1.ColumnStyles.Clear();
this.tableLayoutPanel1.RowStyles.Clear();
this.tableLayoutPanel1.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
this.tableLayoutPanel1.BackColor = Color.White;
this.tableLayoutPanel1.AutoSize = true;
for (int i = 0; i < columnCount; i++)
{
this.tableLayoutPanel1.ColumnStyles.Add(
new ColumnStyle(SizeType.Percent, 100 / columnCount));
}
for (int i = 0; i < rowCount; i++)
{
this.tableLayoutPanel1.RowStyles.Add(
new RowStyle(SizeType.Absolute, 30));
}
this.tableLayoutPanel1.SuspendLayout();
for (var i = 1; i <= 50; i++)
{
var label = new Label();
label.Text = i.ToString();
label.Font = new Font(label.Font, FontStyle.Bold);
label.AutoSize = false;
label.Size = new Size(30, 30);
label.Image = Properties.Resources.Circle;
label.ImageAlign = ContentAlignment.MiddleCenter;
label.TextAlign = ContentAlignment.MiddleCenter;
label.Dock = DockStyle.Fill;
this.tableLayoutPanel1.Controls.Add(label);
}
this.tableLayoutPanel1.ResumeLayout();
或???
或类似的。
然而,据我所知,Scala编译器不支持打字孔。但是,您可以使用undefined
并检查IDE或Emacs + Ensime中的类型,以查看其推断类型。
另请注意,与Haskell的Hindley-Milner类型系统的完整类型推断相比,Scala的类型推断非常小,因此在Scala编译器中使用类似的类型的东西甚至不会太有意义,直到Martin Odersky和维护者决定Scala需要升级类型推断,我认为不太可能很快发生(但Typelevel人群可能会做一些烹饪)。
答案 1 :(得分:2)
对我来说,程序中的漏洞可以帮助我推进实施。它通过告诉我接下来需要什么类型来做到这一点。你可以通过触发常规的Scala类型错误来获得类似的东西。
诀窍是定义一个你知道错误的类型,然后使用它。例如:
object hole
然后,您可以在代码中使用它,您将获得适当的类型错误:
这里的错误告诉我“漏洞”必须是B
,这表明我可以通过某种方式使用g
来取得进展。如果我将代码推进到a => f(g(hole))
,编译器会告诉我hole
需要A
。
这是一种洞,但与其他语言(伊德里斯等)不同......
hole
是可接受的类型!正如您所说???
是一个有用的占位符,但它的类型为Nothing
- 这意味着程序可以编译,但它无助于您填写实现。
至少object hole
虽然有点微不足道,但它确实可以为您提供一些类型信息。
答案 2 :(得分:0)
Chris Birchall提供了一个名为scala-typed-holes
的Scala编译器插件,该插件可实现类型化的孔:
package example
object Example {
def foo(x: Int, y: String): Boolean = {
if (y.length == x) {
??? // TODO implement!
} else {
true
}
}
def bar(x: Int): String = x match {
case 0 => "zero"
case 1 => "one"
case _ => ???
}
}
生成:
[warn] /Users/chris/code/scala-typed-holes/src/test/scala/example/Example.scala:7:7:
[warn] Found hole with type: Boolean
[warn] Relevant bindings include
[warn] x: Int (bound at Example.scala:5:11
[warn] y: String (bound at Example.scala:5:19)
[warn]
[warn] ??? // TODO implement!
[warn] ^
[warn] /Users/chris/code/scala-typed-holes/src/test/scala/example/Example.scala:16:15:
[warn] Found hole with type: String
[warn] Relevant bindings include
[warn] x: Int (bound at Example.scala:13:11)
[warn]
[warn] case _ => ???
[warn] ^