Lens / Prism with error handling

狂风中的少年 提交于 2020-01-01 01:18:07

问题


Let's say I have a pair of conversion functions

string2int :: String -> Maybe Int
int2string :: Int -> String

I could represent these fairly easily using Optics.

stringIntPrism :: Prism String Int

However if I want to represent failure reason, I'd need to keep these as two separate functions.

string2int :: String -> Validation [ParseError] Int
int2string :: Int -> String`

For this simple example Maybe is perfectly fine, since we can always assume that a failure is a parse failure, thus we don't actually have to encode this using an Either or Validation type.

However imagine, in addition to my parsing Prism, I want to perform some validation

isOver18 :: Int -> Validation [AgeError] Int
isUnder55 :: Int -> Validation [AgeError] Int

It would be ideal to be able compose these things together, such that I could have

ageField = isUnder55 . isOver18 . string2Int :: ValidationPrism [e] String Int

This is fairly trivial to build by hand, however it seems like a common enough concept that there might be something lurking in the field of Lenses/Optics that does this already. Is there an existing abstraction that handles this?

tl;dr

Is there a standard way of implementing a partial lens / prism / iso that can be parameterised over an arbitrary functor instead of being tied directly to Maybe?.

I've used Haskell notation above since it's more straight forward, however I'm actually using Monocle in Scala to implement this. I would, however, be perfectly happy with an answer specific to i.e. ekmett's Lens library.


回答1:


I have recently written a blog post about indexed optics; which explores a bit how we can do coindexed optics as well.

In short: Coindexed-optics are possible, but we have yet to do some further research there. Especially, because if we try to translate that approach into lens encoding of lenses (from Profunctor to VL) it gets even more hairy (but I think we can get away with only 7 type-variables).

And we cannot really do this without altering how indexed optics are currently encoded in lens. So for now, you'll better to use validation specific libraries.

To give a hint of the difficulties: When we try to compose with Traversals, should we have

-- like `over` but also return an errors for elements not matched
validatedOver :: CoindexedOptic' s a -> (a -> a) -> s -> (ValidationErrors, s)

or something else? If we could only compose Coindexed Prisms their value won't justify their complexity; they won't "fit" into optics framework.



来源:https://stackoverflow.com/questions/33972337/lens-prism-with-error-handling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!