2016-09-20 53 views
3

Some(Some(Some(Some(10))))中獲得10個最簡潔的方法是什麼?而不需要藉助像斯卡拉斯這樣的外部圖書館。從嵌套選項提取值

+9

如果你有'Option [Option [Option [Option [T]]]]''我認爲你應該重新考慮API結構。 –

+0

最簡潔? 「不要」(如@YuvalItzchakov說:)) –

+0

如果你做的是精巧的程序,並執行一些左外連接,你最終會在選項裏面有選項。上面的問題是誇張的......只是爲了突出問題。 –

回答

10
import scala.language.higherKinds  

case class Flattener[W[_], WW, T](fn : WW => W[T]) 

implicit def optionRecFlattenFn[WW, T](
    implicit f : Flattener[Option, WW, T] = Flattener((ww: WW) => Option(ww)) 
) = Flattener((ww : Option[WW]) => ww.flatMap(f.fn)) 

def optionRecursiveFlatten[WW, T](www : Option[WW])(
    implicit f : Flattener[Option, Option[WW], T] 
) = f.fn(www) 

val nestedOption = Option(Option(Option(Option(10)))) 
// Some(Some(Some(Some(10)))) 

val flatOption = optionRecursiveFlatten(nestedOption) 
// Some(10) 

val evenMoreNestedOption = Option(Option(Option(Option(Option(Option(10)))))) 
// Some(Some(Some(Some(Some(Some(10)))))) 

val flatOption2 = optionRecursiveFlatten(evenMoreNestedOption) 
// Some(10) 
+0

好答案。我仍然不明白,雖然在這個隱式的f:Flattener [Option,WW,T] = Flattener((ww:WW)=> Option(ww))'編譯 – Jatin

+0

@Jatin沒有得到你的問題? –

+0

我的意思是'Flattener((ww:WW)=> Option(ww))''是'Flattener [Option,WW,Option [WW]]'而不是'Flattener [Option,WW,T]'。 我明白它是如何工作的(隱含的只會用於單個選項深度的最後一種情況)。但我感到驚訝的是編譯器在編譯階段沒有提出太多的警告 – Jatin

0

您可以嵌套Option[Option[A]]重複使用flatten

scala> val a = Some(Some(Some(Some(10)))) 
a: Some[Some[Some[Some[Int]]]] = Some(Some(Some(Some(10)))) 

scala> a.flatten.flatten.flatten.get 
res0: Int = 10 

我不認爲有任何通用的,類型安全的方式從T[A] := Option[T[A]] | A提取A


編輯:這種方法可以動態獲取內容,返回是最內層的值,或None

def unwrap(x: Any): Any = x match { 
    case Some(v) => unwrap(v) 
    case v => v 
} 

scala> unwrap(Some(Some(Some(Some(10))))) 
res1: Any = 10 

scala> unwrap(Some(None)) 
res2: Any = None 

它不幸的是過於寬泛類型:Any => Any

4

如果你不提前知道的嵌套級別,這會爲任何級別上工作:

def unwrapRec(o: Option[Any]) : Any = o match { 
    case Some(inner @ Some(_)) => unwrapRec(inner) 
    case Some(x) => x 
    case _ => ??? 
} 

但是,請注意,則返回一個Any。您可以將其更改爲您喜歡的任何類型,並相應地調整模式匹配,但我認爲您必須通過Option[Any]。所以在這一點上它不是安全的。

+1

這顯然不是最理想的b/c類型系統知道什麼是解包。你確實說了這個警告,但4起上訴是四種誤解。 (編輯:不應該推定任何。)有人剛剛發佈了一個typelevel解決方案... –

+0

其實,我懷疑有一個類型安全的解決方案,我很感激,有人發佈它,因爲我無法自己拿出它。這當然會得到我的讚賞。無論如何,因爲這個問題要求最簡潔的方式來從嵌套選項中提取值,所以我寧願不要求upvotes的誤解(特別是不存在類型安全解決方案時)。 – lex82

+0

我知道你的意思。 –