这里真的很简单。看完镜片的精彩介绍后:
http://www.youtube.com/watch?v=efv0SQNde5Q
我想我可能会尝试谈谈中的一个简单例子:
import scalaz.Lens._
fst.andThen(snd).set(((1,2),3),9)
此后出现此错误
error: type mismatch;
found : scalaz.Lens[(Nothing, Nothing),Nothing]
required: scalaz.Lens[(Nothing, Nothing),C]
Note: Nothing <: C, but class Lens is invariant in type B.
You may wish to define B as +B instead. (SLS 4.5)
fst.andThen(snd).set(((1,2),3))
^
关于如何使这项工作的任何想法?
答案 0 :(得分:9)
你需要帮助编译器。以下任何一种都可以:
(fst andThen snd[Int, Int]).set(((1, 2), 3), 9)
或:
(fst[(Int, Int), Int] andThen snd).set(((1, 2), 3), 9)
我的猜测是Edward Kmett在谈话中掩盖了这个问题,因为它与他的主题并不真正相关 - 它只是Scala类型推理系统中的一个(恼人的)怪癖。例如,在Haskell中,以下情况可以正常:
setL (sndLens . fstLens) 9 ((1, 2), 3)
您可以阅读答案here,了解有关Scala中类型推断限制的更多信息。
答案 1 :(得分:6)
不幸的是shapeless的lenses在这种情况下的类型推断不是更好的形式,
scala> import shapeless._ ; import Nat._
import shapeless._
import Nat._
scala> def fst[A, B] = Lens[(A, B)] >> _0
fst: [A, B]=> shapeless.Lens[(A, B),A]
scala> def snd[A, B] = Lens[(A, B)] >> _1
snd: [A, B]=> shapeless.Lens[(A, B),B]
scala> (snd compose fst).set(((1, 2), 3))(9)
<console>:16: error: polymorphic expression cannot be instantiated
to expected type;
found : [A, B]shapeless.Lens[(A, B),A]
required: shapeless.Lens[?,(?, ?)]
(snd compose fst).set(((1, 2), 3))(9)
但是,如果我们撒一些类型的注释,
scala> (snd compose fst[(Int, Int), Int]).set(((1, 2), 3))(9)
res0: ((Int, Int), Int) = ((1,9),3)
问题的根源,无论是在这里还是在scalaz.Lens的情况下,我们需要的是镜头,它们都是值(这样它们可以被组合)和多态(这样我们就可以抽象出元组元素类型) )。无形和斯卡拉斯镜片是价值观,但不是多态的(至少,没有用)。
无形应该能够做得更好......看看这个空间。