Состав линзы Scalaz
Действительно простой вопрос здесь. После просмотра отличного введения в линзы:
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))
^
Любые идеи о том, как сделать эту работу?
Ответы
Ответ 1
Вам понадобится немного помочь компилятору. Любое из следующих действий:
(fst andThen snd[Int, Int]).set(((1, 2), 3), 9)
или
(fst[(Int, Int), Int] andThen snd).set(((1, 2), 3), 9)
Я предполагаю, что Эдвард Кемт замалчивал эту проблему в разговоре, потому что это не имеет особого отношения к его теме - это всего лишь один из (раздражающих) причуд системы вывода типа w60. Например, в Haskell было бы хорошо:
setL (sndLens . fstLens) 9 ((1, 2), 3)
Вы можете прочитать ответы здесь для получения дополнительной информации об ограничениях вывода типа в Scala.
Ответ 2
К сожалению shapeless lenses aren ' t в гораздо лучшей форме по отношению к типу вывода в этом случае,
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, заключается в том, что нам нужны линзы, которые являются обоими значениями (чтобы они могли быть скомпонованы) и полиморфными (чтобы мы могли абстрагироваться от типов элементов кортежа). бесформенные и сказуальные линзы являются значениями, но не являются полиморфными (по крайней мере, не полезными).
бесформенный должен быть в состоянии сделать лучше... смотреть это пространство.