Состав линзы 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, заключается в том, что нам нужны линзы, которые являются обоими значениями (чтобы они могли быть скомпонованы) и полиморфными (чтобы мы могли абстрагироваться от типов элементов кортежа). бесформенные и сказуальные линзы являются значениями, но не являются полиморфными (по крайней мере, не полезными).

бесформенный должен быть в состоянии сделать лучше... смотреть это пространство.