2016-09-20 54 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

我知道你的意思。 –