Search code examples
f#lensesf#+

How to use FSharpPlus.Lens to specify the index of a list?


The sample code of the documentation defines _pageNumber using List._item, but I can't seem to find an example of its use. I tried the following code but it gave an error.

view (Book._pageNumber 1) rayuela // error

How would it be used?


Solution

  • Brian's answer is very accurate from the technical viewpoint but conceptually misses the most important point: you're "viewing" a partial lens (also called prism), instead of "previewing" it. This is not a limitation of F#+, this is just how lens behaves.

    Some background: Prisms or partial lenses are like a lens that can fail, so in principle you can't use the view operation on them because it's an operation that always succeed, or better said doesn't consider a failure, you should use the preview operation which returns an option.

    The composition rules state that the result of composing:

    • a lens with a lens is a lens
    • a lens with a prism (or the other way around) is a prism
    • a prism with a prism is a prism

    This is, as soon as there is a prism in the composition chain the result will be a prism.

    In our case we have _pages << List._item i << _Some which are lens composed with lens composed with _Some which is a prism, so _pageNumber i will be a prism.

    Now, what happens if you use view for a prism? The zero value represents a failure, for instance the zero value of an option is None, but here there is no zero value specified.

    Brian is right in that the error message is misleading, a better error would be "don't use view over a prism", but instead what happen is to try to get a naked value (not inside an option) which can represent failures with zero.

    TL; DR

    use instead:

    preview (Book._pageNumber 1) rayuela // Some { Contents = "The End" }
    

    Someone should send a PR to add that line to the docs.