Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Helpers for ensuring that values are wrapped in a certain type #133

Open
ghost opened this issue Dec 2, 2015 · 11 comments
Open

Helpers for ensuring that values are wrapped in a certain type #133

ghost opened this issue Dec 2, 2015 · 11 comments

Comments

@ghost
Copy link

ghost commented Dec 2, 2015

The counterparts of fns like from-maybe, take a value and ensure that they are wrapped in the correct type.

An example of how it'd behave for Maybe:

(require '[cats.monad.maybe :as maybe])

(maybe/to-maybe (maybe/just 42))
;; => #<Just 42>

(maybe/to-maybe 3)
;; => #<Just 3>

(maybe/to-maybe nil)
;; => #<Nothing>

(maybe/to-maybe (maybe/nothing))
;; => #<Nothing>
@ghost ghost added the contributor friendly label Dec 2, 2015
@muhuk
Copy link
Contributor

muhuk commented Feb 9, 2016

Perhaps also:

(maybe/to-maybe (either/right :foo))
;; => <Just :foo?>

@ghost
Copy link
Author

ghost commented Feb 10, 2016

Definitely, although we may want to be more explicit with that one with something like either->maybe? I think of to-maybe to something akin to Clojure core's ensure-reduced for Reduced so ensure-maybe may be a better name.

@muhuk
Copy link
Contributor

muhuk commented Feb 10, 2016

So it would work like this?

(maybe/to-maybe (either/right :foo))
;; => #<Just #<Left :foo?>>

(maybe/just nil)
;; => #<Just nil>
(maybe/to-maybe nil)
;; => #<Nothing>

@ghost
Copy link
Author

ghost commented Feb 10, 2016

Exactly, that's what I had in mind. I don't know if is the best option though, suggestions welcome.

@yurrriq
Copy link
Collaborator

yurrriq commented Feb 10, 2016

I like that and maybe something like this:

(either->maybe (either/right :foo))
;; => #<Just :foo>

(either->maybe (either/left :bar))
;; => #<Nothing>

I'm not sure that makes sense, though..

Pertinent and interestring:

-- | The 'listToMaybe' function returns 'Nothing' on an empty list
-- or @'Just' a@ where @a@ is the first element of the list.
--
-- ==== __Examples__
--
-- Basic usage:
--
-- >>> listToMaybe []
-- Nothing
--
-- >>> listToMaybe [9]
-- Just 9
--
-- >>> listToMaybe [1,2,3]
-- Just 1
--
-- Composing 'maybeToList' with 'listToMaybe' should be the identity
-- on singleton/empty lists:
--
-- >>> maybeToList $ listToMaybe [5]
-- [5]
-- >>> maybeToList $ listToMaybe []
-- []
--
-- But not on lists with more than one element:
--
-- >>> maybeToList $ listToMaybe [1,2,3]
-- [1]
--
listToMaybe           :: [a] -> Maybe a
listToMaybe []        =  Nothing
listToMaybe (a:_)     =  Just a

@ghost
Copy link
Author

ghost commented Feb 10, 2016

Yep, converting an Either to a Maybe loses information.

@muhuk
Copy link
Contributor

muhuk commented Feb 10, 2016

I'm just playing with the idea. With dynamic typing, things are quite different.

This bothers me a bit:

(bind (maybe/just nil) maybe/to-maybe)
;; => #<Nothing>

I guess I would write (maybe/just 3) instead of (maybe/to-maybe 3) and (maybe/nothing) instead of (maybe/to-maybe nil). And if I had some random value:

(if (some? x)
  (maybe/just x)
  (maybe/nothing))

Which is essentially to-maybe I guess, but clearer {{Citation needed}}.

I guess what bothers me in the end is the ambiguity between nil, (maybe/just nil) & (maybe/to-maybe nil).

@yurrriq
Copy link
Collaborator

yurrriq commented Feb 10, 2016

Maybe we could implement this as a protocol, e.g. MaybeTransformable, and then implement ->maybe for different monads.

Something like:

(defprotocol MaybeTransformable
  (->maybe [mv] "Transform a given monadic value into a Maybe."))

(extend-type Left
  MaybeTransformable
  (->maybe [_] (maybe/nothing)))

(extend-type Right
  MaybeTransformable
  (->maybe [mv] (maybe/just (.-v mv))))

@muhuk
Copy link
Contributor

muhuk commented Feb 10, 2016

Maybe we could implement this as a protocol, e.g. MaybeTransformable and then implement ->maybe for different monads.

I sometimes mzero on either and left-branch later to attach an error message. It would be cool if it would support either as well.


Edit: just checked, I don't call mzero directly.

@ghost
Copy link
Author

ghost commented Feb 15, 2016

I guess what bothers me in the end is the ambiguity between nil, (maybe/just nil) & (maybe/to-maybe nil).

The point of maybe is to get rid of the possibility of every value being null, nil in Clojure's case, so wrapping a nil in a Just is useless and shouldn't be done. I'd go that far to add an assert to the constructor. In Maybe monad's context nil is treated like Nothing.

@muhuk
Copy link
Contributor

muhuk commented Feb 15, 2016

That makes perfect sense. to-maybe would make a good addition if nil isn't allowed as a parameter to maybe/just.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants