2015-09-05 52 views
2

在OCaml中有一個叫'rectype'的東西,它允許遞歸返回類型。爲了說明我的意思,這裏有一個這樣的類型的方法:Scala如何處理遞歸返回類型?

def foo(n: Int)(i: Int): ??? = { 
    val m = n + i 
    (foo(m), m) 
} 

問題是;你在???的地方放什麼?看看你認爲它的代碼是這樣的:

Int => Int => (Int => (Int => (Int => (Int => ... , Int) 

爲什麼?因爲foo(m)的類型是Int => (Int => rep, Int),其中元組中的rep是重複結構。

有沒有辦法做到這一點?

回答

7

當然,斯卡拉有遞歸類型(但可能不是你正在尋找的那種)。採取List,例如(刪節到相關部分):

sealed abstract class List[+A] ... 

final case class ::[B](head: B, tl: List[B]) extends List[B] ... 

object Nil extends List[Nothing] ... 

List(1, 2, 3)遞歸地從多個列表中使用cons ::定義。

1 :: 2 :: 3 :: Nil 

還是沒有中綴表示法:

::(1, ::(2, ::(3, Nil))) 

你可以代表類型這種方式。但請注意,你必須自己定義的類型:

sealed abstract class Inf[A] 

case class Func[A](_1: A => Inf[A], _2: A) extends Inf[A] with Product2[A => Inf[A], A] 

object Identity extends Inf[Nothing] 

def foo(n: Int)(i: Int): Inf[Int] = { 
    val m = n + i 
    Func(foo(m) _, m) 
} 

還是有點更具體:

def foo(n: Int)(i: Int): Func[Int] = { 
    val m = n + i 
    Func(foo(m) _, m) 
} 

scala> val f = foo(5)(3) 
f: Func[Int] = Func(<function1>,8) 


scala> f._1(10) 
res8: Inf[Int] = Func(<function1>,18) 
+0

我需要創造無限的單子!沒有人說它必須是無限的,它只需要承諾它在某個地方是無限的。這可能可以通過懶惰的輸入來完成 –

+0

可以使用Stream()集合創建一個無限系列。有了一個自我指涉的定義,你可以擁有一系列素數,斐波那契數,階乘值等等。我不知道離你有多遠,會讓你成爲一個真正的無限單體。 – jwvh

+0

@ElectricCoffee看我的編輯。也許這可能有幫助。 –

0

在您的特定情況下,返回類型取決於兩個輸入值ni。這兩個在編譯時都是未知的(Scala是靜態類型的!),這意味着編譯器不知道靜態返回類型。這顯然很糟糕,原因很多。

一般來說,既不能定義遞歸類型,也不能utilize type inference for recursive methods

+0

所以基本上沒有在所有 –

+0

都能跟得上這樣的方式。另外,不知道聲明網站的返回類型也是一件壞事。 – Clashsoft

+1

但您確實知道返回類型。這是一個遞歸元組! OCaml通過在幕後進行關閉來處理這個問題(或者我被告知) –