0

For the following code, is it possible in Haskell to combine the bindings? Here is the original code:

Either1 a b = Left1 a | Right1 b

either1 :: Either1 () ()
either1 = Left1 ()

either2 :: Either1 () ()
either2 = Right1 ()

What I want is something like:

Either1 a b = Left1 a | Right1 b

either1 :: Either1 () ()
either1 = Left1 () || Right1 ()

Is this possible? If so, how Could this be done correctly? The above yells a lot about expected types.

I want to know if I can create a single binding that can result in either of the two options. I just want to know if this is possible in any way.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
pmichaels
  • 139
  • 6
  • 2
    How do you want your `either1` to behave? Why do you want this? What feature are you asking for? You ask "Is this possible?" but it's pretty unclear to me what "this" is intended to be. – Daniel Wagner Nov 23 '20 at 16:44
  • I wanted to know if I can create a single binding that can result in either of the two options. I just wanted to know if this is possible in any way. I figured the answer was no, but I am new to Haskell so just wanted to double check – pmichaels Nov 23 '20 at 16:47

2 Answers2

4

One common technique for representing nondeterministic values is to produce a list with one element for each possibility. For example, the nondeterministic choice between Left () and Right () would be written this way:

whoKnows :: [Either () ()] -- read as: nondeterministic choice between multiple
                           -- possible values, each of type Either () ()
whoKnows = [Left (), Right ()]

Later, when you want to do a computation on this nondeterministic value, you can use the list's Monad interface. For example, supposing you have a nondeterministic computation:

couldBeAnything :: Either () () -> [Int] -- read as: nondeterministic function
                                         -- that takes an Either () () and
                                         -- returns an Int
-- implementation left as an exercise for the reader

You could combine the two like this:

soManyPossibilities :: [Int] -- read as: nondeterministic choice between multiple
                             -- possible values, each of type Int                
soManyPossibilities = do
    leftOrRight <- whoKnows
    couldBeAnything leftOrRight

You can also convert deterministic computations into ones that understand how to operate on nondeterministic values with pure or (<$>). For example, if you had

soCertain :: Either () () -> Int

then you could write one of these (they mean the same thing):

fewerOptionsThisTimeMaybe :: [Int]
fewerOptionsThisTimeMaybe = do
    leftOrRight <- whoKnows
    pure (soCertain leftOrRight)
-- OR
fewerOptionsThisTimeMaybe = soCertain <$> whoKnows
Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380
3

No. Something of type Either1 () () can be either Left1 () or Right1 (), but it is still a single, specific value.


Note that Either () () is isomorphic to Bool. A Bool value is either True or False, not an indefinite superposition of the two.

to_bool :: Either () () -> Bool
to_bool (Left ()) = False
to_bool (Right ()) = True

from_bool :: Bool -> Either () ()
from_bool True = Right ()
from_bool False = Left ()

-- I leave it as an exercise to prove that
--  * to_bool . from_bool == id :: Bool -> Bool
--  * from_bool . to_bool == id :: Either () () -> Either () ()
chepner
  • 497,756
  • 71
  • 530
  • 681