# Another Lens Optics type difference

**URL:** https://discourse.haskell.org/t/another-lens-optics-type-difference/13335
**Category:** Learn
**Created:** [November 29, 2025, 12:02am UTC](https://discourse.haskell.org/t/another-lens-optics-type-difference/13335 "2025-11-29T00:02:35Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![feature-not-a-bug](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/feature-not-a-bug/32/2738_2.png) [@feature-not-a-bug](https://discourse.haskell.org/u/feature-not-a-bug)
#### Post date: [November 29, 2025, 12:02am UTC](https://discourse.haskell.org/t/another-lens-optics-type-difference/13335/1 "2025-11-29T00:02:35Z")

</div>

I’m working through the Servant tutorial using `genericServeTWithContext` to serve an endpoint that’s serving a `JWKSet` as JSON along the lines of this guide [Hoist Server With Context for Custom Monads — Servant documentation](https://docs.servant.dev/en/latest/cookbook/hoist-server-with-context/HoistServerWithContext.html)

```haskell
jwksServe :: ReaderT Env Handler JWKSet
jwksServe = do
  t <- asks getJwks
  pure $ jwksPub t

jwksPub :: JWKSet -> JWKSet
jwksPub (JWKSet a) = do -- `a` here is [JWK]
  let pks = mapM (view asPublicKey) a -- Succeeds with `view` from Lens
  case pks of
    Just x -> JWKSet x
    Nothing -> JWKSet []

```

However if I use Optics with

```haskell
  let pks = mapM (view (lensVL asPublicKey)) a -- Fails with `view` from Optics

```

I get the following error leaving me stumped

```haskell
   • Could not deduce ‘Data.Functor.Contravariant.Contravariant f’
        arising from a use of ‘asPublicKey’
      from the context: Functor f
        bound by a type expected by the context:
                   LensVL JWK JWK (Maybe JWK) (Maybe JWK)
        at src/Server.hs:189:32-42
      Possible fix:
        add (Data.Functor.Contravariant.Contravariant f) to the context of
          a type expected by the context:
            LensVL JWK JWK (Maybe JWK) (Maybe JWK)
    • In the first argument of ‘lensVL’, namely ‘asPublicKey’
      In the first argument of ‘view’, namely ‘(lensVL asPublicKey)’
      In the first argument of ‘mapM’, namely
        ‘(view (lensVL asPublicKey))’
    |
189 | let pks = mapM (view (lensVL asPublicKey)) a -- Fails with Optics
    | ^^^^^^^^^^^

```

---

<div class="post-metadata">

### Author: ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)
#### Post date: [November 29, 2025, 9:38am UTC](https://discourse.haskell.org/t/another-lens-optics-type-difference/13335/2 "2025-11-29T09:38:16Z")

</div>

The reason that this doesn’t work is that `asPublicKey` is a `Getter` not a `Lens`. You really need` getterVL` for this, but it doesn’t exist. I don’t know why not, so I opened [an issue](https://github.com/well-typed/optics/issues/533).

In the meantime maybe you could just paste the definition into your project:

```haskell
-- | Type synonym for a van Laarhoven getter.
type GetterVL s a =
  forall f. (Contravariant f, Functor f) => (a -> f a) -> s -> f s

-- | Build a getter from the van Laarhoven representation.
getterVL :: GetterVL s a -> Getter s a
getterVL g = Optic (getting g)

getting :: (Profunctor p, Bicontravariant p) => ((s -> Const s s) -> a -> Const s a) -> p i s c1 -> p i a c2
getting g = lmap (getConst . g Const) . rphantom

```

(for `rphantom` you’ll need to import `Optics.Internal.Bi`)

---

<div class="post-metadata">

### Author: ![feature-not-a-bug](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/feature-not-a-bug/32/2738_2.png) [@feature-not-a-bug](https://discourse.haskell.org/u/feature-not-a-bug)
#### Post date: [November 29, 2025, 11:31am UTC](https://discourse.haskell.org/t/another-lens-optics-type-difference/13335/3 "2025-11-29T11:31:31Z")

</div>

That worked perfectly, thanks. Tested with ghc 9.12

---

<div class="post-metadata">

### Author: ![arybczak](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/arybczak/32/2527_2.png) [@arybczak](https://discourse.haskell.org/u/arybczak)
#### Post date: [July 22, 2026, 6:21pm UTC](https://discourse.haskell.org/t/another-lens-optics-type-difference/13335/4 "2026-07-22T18:21:00Z")

</div>

This will be fixed in optics-core-0.5 (see [Add support for converting to/from VL getters and folds by arybczak · Pull Request #430 · well-typed/optics · GitHub](https://github.com/well-typed/optics/pull/430)).
