10

ここで本当に簡単な質問。レンズの優れた紹介を見た後:

http://www.youtube.com/watch?v=efv0SQNde5Q

私は話でカバーされた簡単な例の1つを試みるかもしれないと思いました:

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))
                      ^

これを機能させる方法について何かアイデアはありますか?

4

2 に答える 2

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 の型推論システムの (厄介な) 癖の 1 つにすぎません。たとえば、Haskell では、次のようにすれば問題ありません。

setL (sndLens . fstLens) 9 ((1, 2), 3)

Scala での型推論の制限の詳細については、こちらの回答を参照してください。

于 2012-08-03T03:23:48.107 に答える
6

残念ながら、shapelessレンズは、この場合の型推論に関してあまり良い形ではありません。

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 の場合でも、問題の根源は、値 (構成できるようにするため) とポリモーフィック (タプル要素型を抽象化できるようにするため) の両方であるレンズが必要だということです。shapeless レンズと scalaz レンズは値ですが、ポリモーフィックではありません (少なくとも、有用ではありません)。

shapeless の方がうまくやれるはずです... このスペースを見てください。

于 2012-08-03T08:56:35.310 に答える