|
1 | 1 | module Data.Options |
2 | 2 | ( Options() |
3 | | - , Option() |
4 | | - , IsOption |
5 | | - , assoc, (:=) |
6 | | - , optionFn |
7 | | - , options |
8 | 3 | , runOptions |
9 | | - , opt, key |
| 4 | + , options |
| 5 | + , Option |
| 6 | + , assoc, (:=) |
| 7 | + , optional |
| 8 | + , opt |
| 9 | + , tag |
| 10 | + , defaultToOptions |
10 | 11 | ) where |
11 | 12 |
|
12 | 13 | import Prelude |
13 | 14 |
|
14 | | -import Data.Foreign (Foreign()) |
15 | | - |
16 | | -import Data.Function (Fn2(), runFn2) |
| 15 | +import Data.Foreign (toForeign, Foreign()) |
| 16 | +import Data.Maybe (Maybe(), maybe) |
| 17 | +import Data.Monoid (mempty, Monoid) |
| 18 | +import Data.Op (Op(Op), runOp) |
| 19 | +import Data.StrMap as StrMap |
| 20 | +import Data.Tuple (Tuple(..)) |
17 | 21 |
|
18 | | -import Data.Maybe (Maybe(..)) |
| 22 | +-- | The `Options` type represents a set of options. The type argument is a |
| 23 | +-- | phantom type, which is useful for ensuring that options for one particular |
| 24 | +-- | API are not accidentally passed to some other API. |
| 25 | +newtype Options opt = |
| 26 | + Options (Array (Tuple String Foreign)) |
19 | 27 |
|
20 | | -import Data.Monoid (Monoid) |
| 28 | +runOptions :: forall opt. Options opt -> Array (Tuple String Foreign) |
| 29 | +runOptions (Options xs) = xs |
21 | 30 |
|
22 | | -import Data.Tuple (Tuple(..)) |
| 31 | +instance semigroupOptions :: Semigroup (Options opt) where |
| 32 | + append (Options xs) (Options ys) = Options (xs <> ys) |
23 | 33 |
|
24 | | -import Unsafe.Coerce (unsafeCoerce) |
| 34 | +instance monoidOptions :: Monoid (Options opt) where |
| 35 | + mempty = Options [] |
25 | 36 |
|
26 | | -foreign import data Options :: * -> * |
| 37 | +-- | Convert an `Options` value into a JavaScript object, suitable for passing |
| 38 | +-- | to JavaScript APIs. |
| 39 | +options :: forall opt. Options opt -> Foreign |
| 40 | +options = toForeign <<< StrMap.fromFoldable <<< runOptions |
27 | 41 |
|
28 | | -foreign import data Option :: * -> * -> * |
| 42 | +-- | An `Option` represents an opportunity to configure a specific attribute |
| 43 | +-- | of a call to some API. This normally corresponds to one specific property |
| 44 | +-- | of an "options" object in JavaScript APIs, but can in general correspond |
| 45 | +-- | to zero or more actual properties. |
| 46 | +type Option opt = Op (Options opt) |
29 | 47 |
|
30 | | -class IsOption value where |
31 | | - assoc :: forall opt. Option opt value -> value -> Options opt |
| 48 | +-- | Associates a value with a specific option. |
| 49 | +assoc :: forall opt value. Option opt value -> value -> Options opt |
| 50 | +assoc o value = runOp o value |
32 | 51 |
|
33 | 52 | infixr 6 := |
34 | 53 |
|
35 | | -(:=) :: forall opt value. (IsOption value) => Option opt value -> value -> Options opt |
| 54 | +-- | An infix version of `assoc`. |
| 55 | +(:=) :: forall opt value. Option opt value -> value -> Options opt |
36 | 56 | (:=) = assoc |
37 | 57 |
|
38 | | -instance semigroupOptions :: Semigroup (Options a) where |
39 | | - append = runFn2 appendFn |
40 | | - |
41 | | -instance monoidOptions :: Monoid (Options a) where |
42 | | - mempty = memptyFn |
43 | | - |
44 | | -instance isOptionString :: IsOption String where |
45 | | - assoc = runFn2 isOptionPrimFn |
46 | | - |
47 | | -instance isOptionBoolean :: IsOption Boolean where |
48 | | - assoc = runFn2 isOptionPrimFn |
49 | | - |
50 | | -instance isOptionNumber :: IsOption Number where |
51 | | - assoc = runFn2 isOptionPrimFn |
52 | | - |
53 | | -instance isOptionInt :: IsOption Int where |
54 | | - assoc = runFn2 isOptionPrimFn |
55 | | - |
56 | | -instance isOptionRecord :: IsOption { | a } where |
57 | | - assoc = runFn2 isOptionPrimFn |
58 | | - |
59 | | -instance isOptionUnit :: IsOption Unit where |
60 | | - assoc = runFn2 isOptionPrimFn |
61 | | - |
62 | | -instance isOptionFunction :: IsOption (a -> b) where |
63 | | - assoc = runFn2 isOptionPrimFn |
64 | | - |
65 | | -instance isOptionArray :: (IsOption a) => IsOption (Array a) where |
66 | | - assoc k vs = joinFn $ assoc (optionFn k) <$> vs |
67 | | - |
68 | | -instance isOptionMaybe :: (IsOption a) => IsOption (Maybe a) where |
69 | | - assoc k Nothing = memptyFn |
70 | | - assoc k (Just a) = assoc (optionFn k) a |
71 | | - |
72 | | -optionFn :: forall opt from to. Option opt from -> Option opt to |
73 | | -optionFn = unsafeCoerce |
74 | | - |
75 | | -key :: forall opt value. Option opt value -> String |
76 | | -key = unsafeCoerce |
77 | | - |
78 | | -opt :: forall opt value. (IsOption value) => String -> Option opt value |
79 | | -opt = unsafeCoerce |
80 | | - |
81 | | -runOptions :: forall a. Options a -> Array (Tuple String Foreign) |
82 | | -runOptions = runOptionsFn Tuple |
83 | | - |
84 | | -foreign import memptyFn :: forall a. Options a |
85 | | - |
86 | | -foreign import appendFn :: forall a. Fn2 (Options a) (Options a) (Options a) |
87 | | - |
88 | | -foreign import joinFn :: forall a b. Array (Options a) -> Options b |
89 | | - |
90 | | -foreign import isOptionPrimFn :: forall b a. Fn2 (Option b a) a (Options b) |
91 | | - |
92 | | -foreign import options :: forall a. Options a -> Foreign |
93 | | - |
94 | | -foreign import runOptionsFn :: forall a. (String -> Foreign -> Tuple String Foreign) -> Options a -> Array (Tuple String Foreign) |
| 58 | +-- | A version of `assoc` which takes possibly absent values. `Nothing` values |
| 59 | +-- | are ignored; passing `Nothing` for the second argument will result in an |
| 60 | +-- | empty `Options`. |
| 61 | +optional :: forall opt value. Option opt value -> Option opt (Maybe value) |
| 62 | +optional option = Op $ maybe mempty (option :=) |
| 63 | + |
| 64 | +-- | The default way of creating `Option` values. Constructs an `Option` with |
| 65 | +-- | the given key, which passes the given value through unchanged. |
| 66 | +opt :: forall opt value. String -> Option opt value |
| 67 | +opt = Op <<< defaultToOptions |
| 68 | + |
| 69 | +-- | Create a `tag`, by fixing an `Option` to a single value. |
| 70 | +tag :: forall opt value. Option opt value -> value -> Option opt Unit |
| 71 | +tag o value = Op \_ -> o := value |
| 72 | + |
| 73 | +-- | The default method for turning a string property key into an |
| 74 | +-- | `Option`. This function simply calls `toForeign` on the value. If |
| 75 | +-- | you need some other behaviour, you can write your own function to replace |
| 76 | +-- | this one, and construct an `Option` yourself. |
| 77 | +defaultToOptions :: forall opt value. String -> value -> Options opt |
| 78 | +defaultToOptions k v = Options [Tuple k (toForeign v)] |
0 commit comments