Skip to content
Brian Marick edited this page Dec 7, 2017 · 5 revisions

Problem 1

It doesn't satisfy the second lens law in all cases. That law says that if you set any part to produce a whole, get on that whole will be Just part. That works if the argument to set is "dawn":

> Lens.set onlyDawn "dawn" |> Lens.get onlyDawn
Just "dawn" : Maybe String

But what if we set to something other than "dawn". The code does this:

> Lens.set onlyDawn "not dawn"
"not dawn" : String

But what will get do with "not dawn". According to the lens law, the result should be Just "not dawn". But it's not:

> Lens.get onlyDawn "not dawn"
Nothing : Maybe String

I don't see any way this can be made to work. There are two cases for Lens.set onlyDawn "not-dawn". The first is that the result is some non-"dawn" value. But then get will produce Nothing, which violates the law.

The second case is that Lens.set onlyDawn "not-dawn" produces "dawn". get would now produce a non-Nothing value (specifically, Just "dawn"). But the law demands that you get back what you set. "dawn" isn't it.

Problem 2

valid : Lens.OneCase String Int
valid =
  Lens.oneCase (String.toInt >> Result.toMaybe) toString

Problem 3

Full source

You can use b2c.set lens to create an entirely new b, and then apply a2b.set to create an entirely new a.

The tricky part is get. You need to handle two a2b.get cases:

  1. a is the wrong wrapper, in which case the whole get must return Nothing.
  2. a is the right wrapper, in which case Just b must be converted to either Nothing or Just c, depending on the value of b. When you have a Maybe x being converted to a Maybe y, Maybe.andThen will probably be useful.
oneCaseAndOneCase : Lens.OneCase a b -> Lens.OneCase b c -> Lens.OneCase a c
oneCaseAndOneCase (Tagged a2b) (Tagged b2c) =
  let
    get =
      a2b.get >> Maybe.andThen b2c.get

    set = 
      b2c.set >> a2b.set
  in
    Lens.oneCase get set

Problem 4

oneCaseToHumble : Lens.OneCase big small -> Lens.Humble big small
oneCaseToHumble (Tagged lens) =
  let
    set small big =
      case lens.get big of
        Nothing ->
          big
        Just _ ->
          lens.set small
  in
    Lens.humble lens.get set

Problem 5

oneCaseAndClassic : Lens.OneCase a b -> Lens.Classic b c -> Lens.Humble a c
oneCaseAndClassic a2b b2c =
  Compose.humbleAndHumble
    (oneCaseToHumble a2b)
    (Compose.classicToHumble b2c)