2011-09-11 33 views
10

我是新的,天真的scala。只知道如何定义一个函数类型,如Set(仅作为示例)。如何在scala中定义类型的函数类型有意义?

type Set = Int => Boolean 

def set(i: Int): Set = n => n == i 
def contains(s: Set, i: Int) = s(i) 

我还阅读了语言无关函数类型的维基。看来C#,C,Haskel也有类似的语法。 http://en.wikipedia.org/wiki/Function_type

我的问题是在这种情况下,你更喜欢定义这种抽象类型函数之一,并使用它, 并没有其他选择来达到相同的目标?比较直接定义一个使用def

或者我可以放宽要求,说使用这个函数类型,我可以使代码看起来好多了。 这样我可以更多地了解功能类型。

在这里我主要感兴趣的部分是type Set = Int => Boolean,当你想抽象出来吗?我正在寻找现实生活中的用例,以及如何在scala语法中以具体的方法来实现它。例如,这个有点复杂。

type Set2 = (Int,Int,String) => (Boolean => Int) => (Boolean => Int). 

我知道它被称为高级类型。语法本身确实是有意义的。 但我只是需要更平实的现实生活中的例子,以斯卡拉初学者。

我找到了这个答案来描述它。 What is a higher kinded type in Scala?

但它对我来说仍然有点模糊。初学者我更喜欢简单的答案。 看起来函数本身并不需要任何东西,除了实现代码的参数和结果类型外。 例如,如果结果(布尔值)不是来自参数(Int),它仍然编译。

def set(i: Int): Set1 = aa => new Date().getDate() == i 

我是不是很擅长?

让我知道为什么这个问题不清楚或不好,所以我可以改进它,先生!

+0

你的语法错综复杂,单词的选择很奇怪或明显错误。例如,“你是否有特别需要定义”没有多大意义,“需要”可能应该是“需求”。其他的例子是顶部的'天真'和你所做的唯一问题'目标'(目标)。这是另一个问题:一个问题应该是一个问题。它以'?'结尾,这是一个问题。在这里,问题在文本的中间,甚至在一个段落的中间。我并没有让你失望,但你并不清楚。 –

+0

@丹尼尔,我已经更新了这个问题。你可以自由修复错误的语法和单词以及任何你想纠正的问题。 –

+0

@丹尼尔,其实我只是不清楚如何在正确的情况下使用这些类型的函数类型。如类型Set2 =(Int,Int,String)=>(Boolean => Int)。它可能会更复杂。 –

回答

28

Scala中的关键字type为给定类型创建一个别名。例如:

scala> type Str = String 
defined type alias Str 

scala> val greeting: Str = "Hello World!" 
greeting: Str = Hello World! 

这是非常相似,你做了什么:

scala> type Set = Int => Boolean 
defined type alias Set 

scala> val isEven: Set = _ % 2 == 0 
isEven: Int => Boolean = <function1> 

scala> println(isEven(4)) 
true 

scala> println(isEven(5)) 
false 

虽然类型别名有时是澄清的目的是有用的,文档是不是他们的主要用例。斯卡拉的类型系统非常复杂。例如,泛型就是一种替代,即抽象类型。试想一下:

// Generics 
abstract class GenericAbstraction[TypeArgument] 
class GenericConcrete extends GenericAbstraction[String] 

// Abstract types 
abstract class TypeAbstraction { 
    type TypeArgument 
} 
class TypeConcrete extends TypeAbstraction { 
    type TypeArgument = String 
} 

这些代码示例基本完成同样的事情,但是有些情况下,你需要抽象类型的情况,但不能(或不应该)使用泛型。你可以找到更多的信息here

+1

谢谢,agilesteel。我能感觉到你的观点。它清除了我所有的误解。我可以使用它进行类型检查吗?测试一个函数是这个抽象函数的子类+1 - Clark Ba​​o 2分钟前编辑 –

+0

我不知道你为什么不能。 – agilesteel

+0

是的。我试着用println(set(1).isInstanceOf [Set]),它返回true。 –

1

可以如下定义函数文本:

val incrementor = (x: Int) => x + 1 

,或者如果你有一些情况下可以由Scala的类型推断被使用,就可以使用还原形式,如:

val listOfInt = List(1, 2, 3, 4, 5) 

listOfInt map {x => x + 1} 
listOfInt map {_ + 1} 

或甚至

listOfInt map {1 +} 

这些文字al l本身意味着这个类型或者它们的类型受到它们传递给它的高阶函数的期望类型的约束。

关于功能和方法之间的差异,有几个问题可能是很好的背景阅读,但也许看看马丁奥德斯基的书的免费版本Programming in Scala (Version 1)将是一个更好的起点读取功能和方法。

+0

谢谢,唐。你的答案很酷,通过展示我的一些函数文字。但是当你使用“type Set = Int => Boolean”时,我更感兴趣。这个语法看起来很酷并且在功能语言方面很特别。我主要关心如何正确使用它,而不是仅仅用它来学习它。 –

+0

As @agilesteel解释说,type关键字用于为类型提供别名。它变得有价值的时候,别名类型很复杂,因此在声明中使用起来很麻烦,并且别名会导致更紧凑和/或更直观的表达式,例如类型PF = PartialFunction [Int,Int]或类型Position = Tuple2 [Int, Int] –

+0

是的,我很清楚。我试过println(classOf [Set]),它打印出“interface scala.Function1”。我打开了Function1,它被定义为一个特征。所以它只是一种特质?这真的很有趣。 –

0

我正在考虑这样。该类型中的函数定义是抽象的,这使得可以定义不同的具体方法来实现它们。我认为它被称为多态或后来的绑定。 ,这使得稍后在运行时绑定函数类型和具体方法成为可能。

我想在JAVA中,你不能用静态方法重写一个抽象方法。但是在函数式语言中,定义抽象函数的具体方法似乎很自然。如果我错了,请纠正我。

看看“多态函数”。

http://gleichmann.wordpress.com/2011/01/23/functional-java-polymorphic-functions/

但结论是可悲的我。我们只能在scala中模拟它。从链接中检查。 “我们发现,在Scala中不可能直接定义多态函数,而是有一些解决它们的方法,这一切都归结为一个事实,即函数是某个Function类型的值,需要在运行时进行类型参数化,即所有类型参数都需要进行类型参数化以获取实际值(或该类型的实例)。“ “作为最后一个结论,定义多态函数是可能的,但其后果可能会超出收益。与往常一样,您需要了解给定的风险并自行决定是否值得权衡(我希望向你展示)你的具体问题领域......“