# \[ANN\] ppx\_viewpattern initial release

**URL:** <https://discuss.ocaml.org/t/ann-ppx-viewpattern-initial-release/9516>\
**Category:** Community\
**Tags:** ppx, announce\
**Created:** [March 14, 2022, 5:51pm UTC](https://discuss.ocaml.org/t/ann-ppx-viewpattern-initial-release/9516 "2022-03-14T17:51:01Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![sim642](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sim642/32/3597_2.png) [@sim642](https://discuss.ocaml.org/u/sim642)\
**Post date:** [March 14, 2022, 5:51pm UTC](https://discuss.ocaml.org/t/ann-ppx-viewpattern-initial-release/9516/1 "2022-03-14T17:51:01Z")

</div>

I’m glad to announce the initial release of [ppx\_viewpattern](https://github.com/sim642/ppx_viewpattern) – transformation for view patterns in OCaml.

It _attempts to_ imitate [Haskell view patterns](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/view_patterns.html). I wrote this ppx rewriter mostly out of curiosity, rather than need, but it turned out neat enough that others might find it interesting or even useful.

## Syntax

Use `[%view? pat when exp]` as a pattern to apply `exp` to whatever the pattern is matching and match the result of the `exp` application against `pat`.  
This is analogous to the Haskell view pattern `exp -> pat`.

The above extension node payload syntax is the best I could come up with to combine an expression and a pattern. Honestly, I was even surprised that `when exp` is attached to a pattern in the AST (not a case), because normally it isn’t part of the pattern itself.

## Example

This allows one to write

```ocaml
(* These cases are exactly like reduction rules! *)
let rec reduce = function
  | Add (Int n1, Int n2) -> Some (Int (n1 + n2))
  | Add ([%view? Some p1' when reduce], p2) -> Some (Add (p1', p2))
  | Add (p1, [%view? Some p2' when reduce]) -> Some (Add (p1, p2'))
  (* ... *)
  | _ -> None

```

instead of

```ocaml
(* These nested cases are so annoying! *)
let rec reduce = function
  | Add (Int n1, Int n2) -> Some (Int (n1 + n2))
  | Add (p1, p2) ->
    begin match reduce p1 with
      | Some p1' -> Some (Add (p1', p2))
      | None ->
        begin match reduce p2 with
          | Some p2' -> Some (Add (p1, p2'))
          | None -> None
        end
    end
  (* ... *)
  | _ -> None

```

See [`examples/` on GitHub](https://github.com/sim642/ppx_viewpattern/tree/master/example) for more.
