2013-03-21 42 views

回答

4

一种方式是使用Bifunctor实例:

scala> val t = (Option(1), Option("str")) 
t: (Option[Int], Option[java.lang.String]) = (Some(1),Some(str)) 

scala> import scalaz._, Scalaz._, Tags._ 
import scalaz._ 
import Scalaz._ 
import Tags._ 

scala> t.bimap(First, First) 
res0: ([email protected]@[Option[Int],scalaz.Tags.First], [email protected]@[Option[java.lang.String],scalaz.Tags.First]) = (Some(1),Some(str)) 

更习惯的方法(好吧,一个更通用的方法:将任何元组,特里普尔等工作)可能会被使用到shapeless将你的元组变成HList,然后应用自然转换Option[A] ~> Option[A] @@ First。这里有一个粗略的实现这一点:

scala> import scalaz._, Scalaz._, Tags._ 
import scalaz._ 
import Scalaz._ 
import Tags._ 

scala> import shapeless._, Tuples._, Nat._ 
import shapeless._ 
import Tuples._ 
import Nat._ 

scala> val t = (Option(1), Option("str")) 
t: (Option[Int], Option[String]) = (Some(1),Some(str)) 

scala> object optionToFirstoption extends (Option ~> FirstOption) { 
    | def apply[A](fa: Option[A]): Option[A] @@ First = First(fa) 
    | } 
defined module optionToFirstoption 

scala> t.hlisted.map(optionToFirstoption).tupled 
res1: (Option[Int] with scalaz.Tagged[scalaz.Tags.First], Option[String] with scalaz.Tagged[scalaz.Tags.First]) = (Some(1),Some(str)) 
+2

不错,但我会质疑使用“更地道”在这里;-) – 2013-03-22 13:55:37

+0

@MilesSabin Yyeah,一个“更多的铁杆”可能会形容这是怎么回事更好:) – folone 2013-03-22 13:59:15

+0

好吧,还有一个问题:是否可以在不写整个'Monoid [Option [T]]'的情况下使Monoid Default的FirstOption实现?例如。 'implicit def firstOptionMonoid [T] = implicitly [Monoid [FirstOption [T]]]' - 这显然不起作用,但我能想到的方式真的很冗长(隐式def firstOptionMonoid [T] = new Monoid [T] { def append(...)= implicitly [Monoid [FirstOption [T]]] append(...); def zero = ...}) – 2013-03-22 17:55:24