4

The Prism' here comes from optics-core not lens. Is there a way to simplify this implementation, or is this as simple as it gets?

{- | Given two @Prism'@'s whose filepaths are distinct (ie., both @a@ and @b@
 encode to distinct filepaths), return a new @Prism'@ that combines both.

 If this distinctness property does not hold between the input @Prism'@'s, then
 the resulting @Prism'@ will not be lawful.
-}
eitherPrism :: Prism' FilePath a -> Prism' FilePath b -> Prism' FilePath (Either a b)
eitherPrism p1 p2 =
  prism'
    ( either
        (review p1)
        (review p2)
    )
    ( \fp ->
        asum
          [ Left <$> preview p1 fp
          , Right <$> preview p2 fp
          ]
    )
Sridhar Ratnakumar
  • 81,433
  • 63
  • 146
  • 187
  • Is this a lawful prism? You the two prisms to be disjoint, I think, otherwise you could put in a `Right` with `re` and get a `Left` back out – Benjamin Hodgson Jul 18 '22 at 16:02
  • like, `let bad = eitherPrism _Just _Just in matching bad (review bad (Right (Just "abc")))` will return `Right (Left (Just "abc"))` I think, whereas the laws require it to be `Right (Right (Just "abc"))`. (This is akin to horizontal composition of traversals wherein you need the two traversals to point at different parts of the thing.) – Benjamin Hodgson Jul 18 '22 at 16:05
  • i guess that doesn't type check but you get the idea, put the same prism in for both parameters, `review` a `Right` value, then use `matching` and get a `Left` out – Benjamin Hodgson Jul 18 '22 at 16:14
  • @BenjaminHodgson This combinator is used to combine sub routes [in Ema](https://github.com/EmaApps/ema/blob/89ef58cebe0de996a68e9d2c281af968d34e820b/src/Ema/Route/Prism.hs#L38-L50). If you have `data R = R_Foo Foo | R_Bar Bar`, then the resulting prism will try to `preview` first prism (Foo) and if that fails `preview` the second prism (Bar). This is in line with the semantics of route decoding (first constructor before second; so forth). Is there a route-specific example that you think behaves incorrectly? – Sridhar Ratnakumar Jul 18 '22 at 23:31
  • `eitherPrism _R_Foo _R_Foo` will not be a lawful prism. – Benjamin Hodgson Jul 19 '22 at 00:34
  • Yes, the encoding of input prisms must be distinct for the output prism to be lawful. [I clarified it here](https://github.com/EmaApps/ema/commit/3cffc1c9e89ca1e99109da42625d4dce957f51ca) (as well as edited the SO question); let me know if that is sufficient. In routes for static sites, users must ensure that no two route values encode to the same `.html` file. Ema checks for it at runtime; see `Ema.Route.Prism.Check`. – Sridhar Ratnakumar Jul 19 '22 at 13:45

0 Answers0