Following code illustrates my intention. I want to pattern match, if it doesn't result is Nothing
, if matches result is Just something
data MyData =
A Int
| B String
| C
ifA (A i) = Just i
ifA _ = Nothing
ifB (B str) = Just str
ifB _ = Nothing
ifC C = Just ()
ifC _ = Nothing
mbMult3 i = Just (i*3)
concWorld str = Just (str ++ "World")
example1 v = ifA v >>= mbMult3
example2 v = ifB v >>= concWorld
-- example2 (B "Hello ,") == Just "Hello, World"
-- example2 (A 3) == Nothing
Are there other ways to do ifA
ifB
ifC
.
Edit:
lens
library might have something. But I know nothing about lens
for now.ifC
Prisms† from the lens package model this. You can generate prisms for your type using makePrisms
, then use ^?
(or its prefix equivalent, preview
) to access members of the sum type, producing Nothing
if a different value is provided:
{-# LANGUAGE TemplateHaskell #-}
import Control.Lens
data MyData
= A Int
| B String
| C
deriving (Show)
makePrisms ''MyData
ghci> A 42 ^? _A
Just 42
ghci> A 42 ^? _B
Nothing
ghci> C ^? _C
Just ()
The nice thing about prisms is that they compose with other optics (e.g. lenses, folds, and traversals), as well as use them to traverse through nested sum types by composing prisms:
ghci> (A 42, C) ^? _1._A
Just 42
ghci> (B "hello", C) ^? _1._A
Nothing
ghci> Just (A 42) ^? _Just._A
Just 42
ghci> Just (B "hello") ^? _Just._A
Nothing
ghci> Nothing ^? _Just._A
Nothing
The lens package is fairly complicated, and explaining all of its features is well outside the scope of this answer. If you don’t need much of it, your solution is probably fine. But if you find yourself writing that sort of code a lot, it’s likely that lens can help, as long as you’re willing to accept the steep learning curve and often-confusing type errors.
† More generally, ^?
works on any Fold
that produces zero or one value (or more, it just ignores all but the first one), but prisms are specifically designed with sum types in mind, so they are more relevant here.