17

Say I have

x = Just 2

Is there a way (preferrably a builtin mechanism/function) to use x in a single statement such that if it is a Just, then the 2 is automatically unwrapped and used, and if it is a Nothing, an exception is raised?

That is,

(f x) + 2 == 4 if x == Just 2, and raises an exception if x == Nothing.

Don Stewart
  • 137,316
  • 36
  • 365
  • 468
me2
  • 3,069
  • 2
  • 26
  • 33

3 Answers3

30

Data.Maybe.fromJust has been mentioned by other answers already:

fromJust :: Maybe a -> a
fromJust Nothing  = error "Maybe.fromJust: Nothing"
fromJust (Just x) = x

There's also maybe (found in both Prelude and Data.Maybe):

maybe :: b -> (a -> b) -> Maybe a -> b
maybe n _ Nothing  = n
maybe _ f (Just x) = f x

fromJust can be written using maybe:

fromJust = maybe (error "Maybe.fromJust: Nothing") id

As you can see, maybe allows you flexibility in handling both cases without requiring pattern matching:

\x -> maybe 0 (+ 2) x  -- Nothing -> 0, Just 2 -> 4

Similarly, Prelude and Data.Either have either :: (a -> c) -> (b -> c) -> Either a b -> c:

\x -> either (subtract 1) (* 2) x  -- Left 5 -> 4, Right 3 -> 6

If you define a data type

data MyDataType
  = TypeA { foo :: Int, bar :: String }
  | TypeB { foo :: Int,                baz :: () }
  | TypeC {             bar :: String, baz :: () }

like this, you end up with partial functions for accessors.

foo :: MyDataType -> Int
bar :: MyDataType -> String
baz :: MyDataType -> ()

They're called partial functions, as opposed to total functions, because they only return results for a subset of their inputs.

foo (TypeA { foo = 15, bar = "hello!" })  -- 15
bar (TypeB { foo = 12345679, baz = () })  -- error
ephemient
  • 198,619
  • 38
  • 280
  • 391
12

For this particular case, fromJust. In general

let Just k = x in f k + 2 == 4

This trick works with any datatype constructor and is very commonly used with (:) for nonempty lists.

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
10

fromJust should do what you want.

Tom
  • 43,583
  • 4
  • 41
  • 61
  • The needed [package](https://hackage.haskell.org/package/base-4.17.0.0/docs/Data-Maybe.html) is `import Data.Maybe`. – Ahmad Ismail Nov 10 '22 at 07:52