-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
option.cljc
105 lines (88 loc) · 2.58 KB
/
option.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
(ns monnit.option
(:refer-clojure :exclude [some some?])
(:require [monnit.core :as m]
[monnit.impl.util :refer [typecase]]))
(defprotocol Option
(option? [self])
(some? [self])
(none? [self])
(-run-option [self default f]))
(extend-protocol Option
#?(:clj Object, :cljs default)
(option? [_] false)
(none? [_] false)
(some? [_] false)
(-run-option [self _ _]
(assert false (str "-run-option called on non-Option value " self)))
nil
(option? [_] false)
(none? [_] false)
(some? [_] false)
(-run-option [self _ _]
(assert false (str "-run-option called on non-Option value " self))))
(defrecord None []
Option
(option? [_] true)
(none? [_] true)
(some? [_] false)
(-run-option [_ default _] default)
m/Functor
(-fmap [self _] self)
(-fmap [self _ _] self)
(-fmap [self _ _ _] self)
(-fmap [self _ _ _ _] self)
(-fmap [self _ _ _ _ _] self)
m/Monad
(bind [self _] self)
m/Alternative
(alt [_ other] other))
(def none (None.))
(defrecord Some [value]
Option
(option? [_] true)
(none? [_] false)
(some? [_] true)
(-run-option [_ _ f] (f value))
m/Functor
(-fmap [_ f] (Some. (f value)))
(-fmap [_ f b]
(typecase [b b]
Some (Some. (f value (.-value b)))
None b))
(-fmap [_ f b c]
(typecase [b b]
Some (typecase [c c]
Some (Some. (f value (.-value b) (.-value c)))
None c)
None b))
(-fmap [_ f b c d]
(typecase [b b]
Some (typecase [c c]
Some (typecase [d d]
Some (Some. (f value (.-value b) (.-value c) (.-value d)))
None d)
None c)
None b))
(-fmap [_ f b c d args]
(typecase [b b]
Some (typecase [c c]
Some (typecase [d d]
Some (let [args (reduce (fn [args arg]
(typecase [arg arg]
Some (conj! args (.-value arg))
None (reduced arg)))
(transient []) args)]
(if (instance? None args)
args
(Some. (apply f value (.-value b) (.-value c) (.-value d) (persistent! args)))))
None d)
None c)
None b))
m/Monad
(bind [_ f] (f value))
m/Alternative
(alt [self _] self))
(def some ->Some)
(def pure some)
(defmethod m/pure Option [_ v] (pure v))
(defn run [default f e] (-run-option e default f))