├── package.json ├── .gitignore ├── src └── RxJS │ ├── Subscription.js │ ├── Scheduler.js │ ├── Subscriber.purs │ ├── Notification.purs │ ├── Subscription.purs │ ├── Scheduler.purs │ ├── Observable.js │ └── Observable.purs ├── .travis.yml ├── test ├── Main.purs ├── ObservableTSpec.purs └── ObservableSpec.purs ├── pnpm-lock.yaml ├── README.md ├── spago.dhall ├── packages.dhall └── LICENSE /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "rxjs": "^7" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bower_components/ 2 | /node_modules/ 3 | /.pulp-cache/ 4 | /output/ 5 | /.psc* 6 | /.psa* 7 | /yarn.lock 8 | /src/Main.purs 9 | /npm-debug.log 10 | /.vscode 11 | /.spago -------------------------------------------------------------------------------- /src/RxJS/Subscription.js: -------------------------------------------------------------------------------- 1 | /* global exports */ 2 | "use strict"; 3 | 4 | // module RxJS.Subscription 5 | 6 | export const unsubscribe = function(sub){ 7 | return function(){ 8 | sub.unsubscribe(); 9 | }; 10 | }; 11 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "12" 5 | 6 | before_script: 7 | - npm install -g purescript pulp psc-package spago 8 | - npm install rxjs 9 | - spago build 10 | 11 | script: 12 | - spago test 13 | -------------------------------------------------------------------------------- /src/RxJS/Scheduler.js: -------------------------------------------------------------------------------- 1 | /* global exports */ 2 | "use strict"; 3 | 4 | // module RxJS.Scheduler 5 | 6 | import * as Rx from 'rxjs'; 7 | 8 | export const queue = Rx.queueScheduler; 9 | export const asap = Rx.asapScheduler; 10 | export const async = Rx.asyncScheduler; 11 | export const animationFrame = Rx.animationFrameScheduler; 12 | -------------------------------------------------------------------------------- /src/RxJS/Subscriber.purs: -------------------------------------------------------------------------------- 1 | module RxJS.Subscriber 2 | (Subscriber) 3 | where 4 | 5 | import Prelude (Unit) 6 | import Effect (Effect) 7 | import Effect.Exception (Error) 8 | 9 | type Subscriber a 10 | = { next :: a -> Effect Unit 11 | , error :: Error -> Effect Unit 12 | , completed :: Unit -> Effect Unit 13 | } 14 | -------------------------------------------------------------------------------- /src/RxJS/Notification.purs: -------------------------------------------------------------------------------- 1 | 2 | module RxJS.Notification where 3 | 4 | import Prelude 5 | import Effect.Exception (Error(), message) 6 | 7 | data Notification a = OnError Error | OnNext a | OnComplete 8 | 9 | instance showNotification :: (Show a) => Show (Notification a) where 10 | show (OnNext v) = "(OnNext " <> show v <> ")" 11 | show (OnError err) = "(OnError " <> message err <> ")" 12 | show (OnComplete) = "(OnComplete)" 13 | -------------------------------------------------------------------------------- /src/RxJS/Subscription.purs: -------------------------------------------------------------------------------- 1 | module RxJS.Subscription 2 | ( Subscription(..) 3 | , unsubscribe 4 | ) where 5 | 6 | import Prelude (Unit) 7 | import Effect 8 | 9 | -- | When you subscribe, you get back a Subscription, which represents the 10 | -- | ongoing execution. 11 | foreign import data Subscription :: Type 12 | 13 | -- | Call unsubscribe() to cancel the execution. 14 | foreign import unsubscribe :: Subscription -> Effect Unit 15 | -------------------------------------------------------------------------------- /test/Main.purs: -------------------------------------------------------------------------------- 1 | module Test.Main where 2 | 3 | import Effect (Effect) 4 | import ObservableSpec (observableOperatorSpec, observableCreationSpec) 5 | import ObservableTSpec (observableTOperatorSpec, observableTCreationSpec) 6 | import Prelude (Unit, discard) 7 | import Test.Unit.Main (exit, runTest) 8 | 9 | main :: Effect Unit 10 | main = do 11 | runTest do 12 | observableOperatorSpec 13 | observableCreationSpec 14 | observableTOperatorSpec 15 | observableTCreationSpec 16 | (exit 0) 17 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: 5.3 2 | 3 | specifiers: 4 | rxjs: ^7 5 | 6 | devDependencies: 7 | rxjs: 7.5.2 8 | 9 | packages: 10 | 11 | /rxjs/7.5.2: 12 | resolution: {integrity: sha512-PwDt186XaL3QN5qXj/H9DGyHhP3/RYYgZZwqBv9Tv8rsAaiwFH1IsJJlcgD37J7UW5a6O67qX0KWKS3/pu0m4w==} 13 | dependencies: 14 | tslib: 2.3.1 15 | dev: true 16 | 17 | /tslib/2.3.1: 18 | resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==} 19 | dev: true 20 | -------------------------------------------------------------------------------- /src/RxJS/Scheduler.purs: -------------------------------------------------------------------------------- 1 | module RxJS.Scheduler 2 | ( Scheduler(..) 3 | , queue 4 | , asap 5 | , async 6 | , animationFrame 7 | ) 8 | where 9 | 10 | -- | Please see [RxJS Version 6.* documentation](http://reactivex.io/rxjs/) for 11 | -- | additional details on proper usage of the library. 12 | 13 | foreign import data Scheduler :: Type 14 | 15 | foreign import queue :: Scheduler 16 | 17 | foreign import asap :: Scheduler 18 | 19 | foreign import async :: Scheduler 20 | 21 | foreign import animationFrame :: Scheduler 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # purescript-rxps 2 | 3 | An opinionated PureScript wrapper for RxJS, complete with a Monad Transformer `ObservableT` 4 | 5 | This module has had an ownership transfer to where to https://github.com/waynevanson/purescript-rxps 6 | 7 | ### Installation 8 | 9 | ```bash 10 | npm install rxjs 11 | spago install purescript-rxps 12 | ``` 13 | 14 | ### Documentation 15 | 16 | - Module documentation is [published on Pursuit](http://pursuit.purescript.org/packages/purescript-rxps). 17 | 18 | ### Contributing 19 | 20 | ```sh 21 | gh repo fork lukajcb/purescript-rxps 22 | pnpm i 23 | spago test --watch 24 | ``` 25 | -------------------------------------------------------------------------------- /spago.dhall: -------------------------------------------------------------------------------- 1 | {- 2 | Welcome to a Spago project! 3 | You can edit this file as you like. 4 | 5 | Need help? See the following resources: 6 | - Spago documentation: https://github.com/purescript/spago 7 | - Dhall language tour: https://docs.dhall-lang.org/tutorials/Language-Tour.html 8 | 9 | When creating a new Spago project, you can use 10 | `spago init --no-comments` or `spago init -C` 11 | to generate this file without the comments in this block. 12 | -} 13 | { name = "my-project" 14 | , dependencies = 15 | [ "arrays" 16 | , "control" 17 | , "effect" 18 | , "exceptions" 19 | , "foldable-traversable" 20 | , "functions" 21 | , "identity" 22 | , "partial" 23 | , "prelude" 24 | , "psci-support" 25 | , "strings" 26 | , "test-unit" 27 | , "transformers" 28 | , "tuples" 29 | , "web-events" 30 | , "control" 31 | , "foldable-traversable" 32 | , "identity" 33 | , "partial" 34 | , "strings" 35 | , "transformers" 36 | , "tuples" 37 | , "web-events" 38 | , "foreign-object" 39 | ] 40 | -- , devDependencies = ["test-unit"] 41 | , packages = ./packages.dhall 42 | , sources = [ "src/**/*.purs", "test/**/*.purs" ] 43 | } 44 | -------------------------------------------------------------------------------- /packages.dhall: -------------------------------------------------------------------------------- 1 | {- 2 | Welcome to your new Dhall package-set! 3 | 4 | Below are instructions for how to edit this file for most use 5 | cases, so that you don't need to know Dhall to use it. 6 | 7 | ## Use Cases 8 | 9 | Most will want to do one or both of these options: 10 | 1. Override/Patch a package's dependency 11 | 2. Add a package not already in the default package set 12 | 13 | This file will continue to work whether you use one or both options. 14 | Instructions for each option are explained below. 15 | 16 | ### Overriding/Patching a package 17 | 18 | Purpose: 19 | - Change a package's dependency to a newer/older release than the 20 | default package set's release 21 | - Use your own modified version of some dependency that may 22 | include new API, changed API, removed API by 23 | using your custom git repo of the library rather than 24 | the package set's repo 25 | 26 | Syntax: 27 | where `entityName` is one of the following: 28 | - dependencies 29 | - repo 30 | - version 31 | ------------------------------- 32 | let upstream = -- 33 | in upstream 34 | with packageName.entityName = "new value" 35 | ------------------------------- 36 | 37 | Example: 38 | ------------------------------- 39 | let upstream = -- 40 | in upstream 41 | with halogen.version = "master" 42 | with halogen.repo = "https://example.com/path/to/git/repo.git" 43 | 44 | with halogen-vdom.version = "v4.0.0" 45 | with halogen-vdom.dependencies = [ "extra-dependency" ] # halogen-vdom.dependencies 46 | ------------------------------- 47 | 48 | ### Additions 49 | 50 | Purpose: 51 | - Add packages that aren't already included in the default package set 52 | 53 | Syntax: 54 | where `` is: 55 | - a tag (i.e. "v4.0.0") 56 | - a branch (i.e. "master") 57 | - commit hash (i.e. "701f3e44aafb1a6459281714858fadf2c4c2a977") 58 | ------------------------------- 59 | let upstream = -- 60 | in upstream 61 | with new-package-name = 62 | { dependencies = 63 | [ "dependency1" 64 | , "dependency2" 65 | ] 66 | , repo = 67 | "https://example.com/path/to/git/repo.git" 68 | , version = 69 | "" 70 | } 71 | ------------------------------- 72 | 73 | Example: 74 | ------------------------------- 75 | let upstream = -- 76 | in upstream 77 | with benchotron = 78 | { dependencies = 79 | [ "arrays" 80 | , "exists" 81 | , "profunctor" 82 | , "strings" 83 | , "quickcheck" 84 | , "lcg" 85 | , "transformers" 86 | , "foldable-traversable" 87 | , "exceptions" 88 | , "node-fs" 89 | , "node-buffer" 90 | , "node-readline" 91 | , "datetime" 92 | , "now" 93 | ] 94 | , repo = 95 | "https://github.com/hdgarrood/purescript-benchotron.git" 96 | , version = 97 | "v7.0.0" 98 | } 99 | ------------------------------- 100 | -} 101 | let upstream = 102 | https://github.com/purescript/package-sets/releases/download/psc-0.15.4-20221226/packages.dhall 103 | sha256:a3a813f832979282e20ee32d85bed28b41ce9587ea1f62fc640f53c7fa1dfd66 104 | 105 | in upstream 106 | -------------------------------------------------------------------------------- /test/ObservableTSpec.purs: -------------------------------------------------------------------------------- 1 | module ObservableTSpec (observableTOperatorSpec, observableTCreationSpec) where 2 | 3 | import RxJS.Observable 4 | import Control.Bind (join) 5 | import Effect (Effect) 6 | import Control.Comonad (extract) 7 | import Effect.Class (liftEffect) 8 | import Control.MonadPlus (empty) 9 | import Data.String (length) 10 | import Data.Identity (Identity) 11 | import Prelude (Unit, bind, const, map, pure, unit, (#), (<), (>), discard) 12 | import Test.Unit (TestSuite, suite, test) 13 | 14 | 15 | observableTCreationSpec :: TestSuite 16 | observableTCreationSpec = 17 | suite "observableT creation methods" do 18 | test "interval" do 19 | liftEffect ((interval 200 # take 2) # subObservable) 20 | test "timer" do 21 | liftEffect ((timer 200 100 # take 2) # subObservable) 22 | test "never" do 23 | liftEffect ((never) # subObservable) 24 | test "empty" do 25 | liftEffect ((empty) # subObservable) 26 | test "range" do 27 | liftEffect ((range 0 5) # subObservable) 28 | test "fromArray" do 29 | liftEffect ((fromArray [1,2,3,4,5]) # subObservable) 30 | test "just" do 31 | liftEffect ((just "Hello World!") # subObservable) 32 | test "create" do 33 | liftEffect ((create (\observer -> observer.next 34)) # subCreation) 34 | 35 | observableTOperatorSpec :: TestSuite 36 | observableTOperatorSpec = 37 | suite "observableT operators" do 38 | test "auditTime" do 39 | liftEffect ((auditTime 200 observable) # subObservable) 40 | test "bufferCount" do 41 | liftEffect ((bufferCount 2 1 observable) # subObservable) 42 | test "combineLatest" do 43 | liftEffect ((combineLatest (\acc cur -> acc) observable observable2) # subObservable) 44 | test "concat" do 45 | liftEffect ((concat observable observable3) # subObservable) 46 | test "count" do 47 | liftEffect ((count observable) # subObservable) 48 | test "debounceTime" do 49 | liftEffect ((debounceTime 1000 observable) # subObservable) 50 | test "defaultIfEmpty" do 51 | liftEffect ((defaultIfEmpty 0 observable) # subObservable) 52 | test "delay" do 53 | liftEffect ((delay 200 observable) # subObservable) 54 | test "distinct" do 55 | liftEffect ((distinct observable) # subObservable) 56 | test "distinctUntilChanged" do 57 | liftEffect ((distinctUntilChanged observable) # subObservable) 58 | test "elementAt" do 59 | liftEffect ((elementAt 2 observable) # subObservable) 60 | test "every" do 61 | liftEffect ((every (_ > 3) observable # subObservable)) 62 | test "filter" do 63 | liftEffect ((filter (_ > 2) observable) # subObservable) 64 | test "ignoreElements" do 65 | liftEffect ((ignoreElements observable) # subObservable) 66 | test "isEmpty" do 67 | liftEffect ((isEmpty observable) # subObservable) 68 | test "first" do 69 | liftEffect ((first (const true) observable # subObservable)) 70 | test "last" do 71 | liftEffect ((last (const true) observable # subObservable)) 72 | test "map" do 73 | liftEffect ((map length observable2) # subObservable) 74 | test "mapTo" do 75 | liftEffect ((mapTo "A" observable) # subObservable) 76 | test "merge" do 77 | liftEffect ((merge observable observable3) # subObservable) 78 | --test "mergeAll" do 79 | --liftEffect ((mergeAll_ higherOrder) # subObservable) 80 | --test "mergeMap" do 81 | --liftEffect ((mergeMap observable (\a -> observable3)) # subObservable) 82 | test "reduce" do 83 | liftEffect ((reduce (\acc cur -> acc) 0 observable) # subObservable) 84 | test "scan" do 85 | liftEffect ((scan (\acc cur -> acc) 0 observable) # subObservable) 86 | test "retry" do 87 | liftEffect ((retry 10 observable) # subObservable) 88 | test "sample" do 89 | liftEffect ((sample observable observable2) # subObservable) 90 | test "sampleTime" do 91 | liftEffect ((sampleTime 1000 observable) # subObservable) 92 | test "share" do 93 | liftEffect ((share observable) # subObservable) 94 | test "skip" do 95 | liftEffect ((skip 2 observable) # subObservable) 96 | test "skipUntil" do 97 | liftEffect ((skipUntil observable observable2) # subObservable) 98 | test "skipWhile" do 99 | liftEffect ((skipWhile (_ < 2) observable) # subObservable) 100 | test "startWith" do 101 | liftEffect ((startWith 0 observable) # subObservable) 102 | test "take" do 103 | liftEffect ((take 3 observable) # subObservable) 104 | test "takeWhile" do 105 | liftEffect ((takeWhile (_ < 4) observable) # subObservable) 106 | test "takeUntil" do 107 | liftEffect ((takeUntil observable observable3) # subObservable) 108 | test "throttleTime" do 109 | liftEffect ((throttleTime 200 observable) # subObservable) 110 | test "withLatestFrom" do 111 | liftEffect ((withLatestFrom (\a b -> a) observable observable2) # subObservable) 112 | 113 | 114 | observable :: ObservableT Identity Int 115 | observable = fromArray [1,2,3,4,5,6] 116 | 117 | observable2 :: ObservableT Identity String 118 | observable2 = fromArray ["h","e","ll","o"] 119 | 120 | observable3 :: ObservableT Identity Int 121 | observable3 = fromArray [6,5,4,3,2,1] 122 | 123 | higherOrder :: ObservableT Identity (ObservableT Identity String) 124 | higherOrder = just observable2 125 | 126 | subCreation :: forall a. ObservableT Effect a -> Effect Unit 127 | subCreation obs = do 128 | sub <- join (obs # subscribeNext noop) 129 | pure unit 130 | 131 | subObservable :: forall a. ObservableT Identity a -> Effect Unit 132 | subObservable obs = do 133 | sub <- extract (obs # subscribeNext noop) 134 | pure unit 135 | 136 | noop :: forall a. a -> Effect Unit 137 | noop a = pure unit 138 | -------------------------------------------------------------------------------- /test/ObservableSpec.purs: -------------------------------------------------------------------------------- 1 | module ObservableSpec (observableOperatorSpec, observableCreationSpec) where 2 | 3 | import RxJS.Observable 4 | import Control.Comonad (extract) 5 | import Effect (Effect) 6 | import Effect.Class (liftEffect) 7 | import Control.MonadPlus (empty) 8 | import Data.String (length) 9 | import Prelude (Unit, bind, const, map, pure, unit, (#), (<), (>), discard) 10 | import Test.Unit (TestSuite, suite, test) 11 | 12 | observableCreationSpec :: TestSuite 13 | observableCreationSpec = 14 | suite "observable creation methods" do 15 | test "interval" do 16 | liftEffect ((interval 200 # take 2) # subObservable) 17 | test "timer" do 18 | liftEffect ((timer 200 100 # take 2) # subObservable) 19 | test "never" do 20 | liftEffect ((never) # subObservable) 21 | test "empty" do 22 | liftEffect ((empty) # subObservable) 23 | test "range" do 24 | liftEffect ((range 0 5) # subObservable) 25 | test "fromArray" do 26 | liftEffect ((fromArray [1,2,3,4,5]) # subObservable) 27 | test "just" do 28 | liftEffect ((just "Hello World!") # subObservable) 29 | 30 | observableOperatorSpec :: TestSuite 31 | observableOperatorSpec = 32 | suite "observable operators" do 33 | test "auditTime" do 34 | liftEffect ((auditTime 200 observable) # subObservable) 35 | test "bufferCount" do 36 | liftEffect ((bufferCount 2 1 observable) # subObservable) 37 | test "combineLatest" do 38 | liftEffect ((combineLatest (\acc cur -> acc) observable observable2) # subObservable) 39 | test "concat" do 40 | liftEffect ((concat observable observable3) # subObservable) 41 | test "concatAll" do 42 | liftEffect ((concatAll higherOrder) # subObservable) 43 | test "concatMap" do 44 | liftEffect ((concatMap (\n -> just n) observable) # subObservable) 45 | test "count" do 46 | liftEffect ((count observable) # subObservable) 47 | test "debounce" do 48 | liftEffect ((debounce (\x -> observable) observable3) # subObservable) 49 | test "debounceTime" do 50 | liftEffect ((debounceTime 1000 observable) # subObservable) 51 | test "defaultIfEmpty" do 52 | liftEffect ((defaultIfEmpty 0 observable) # subObservable) 53 | test "delay" do 54 | liftEffect ((delay 200 observable) # subObservable) 55 | test "delayWhen" do 56 | liftEffect ((delayWhen (\x -> observable2) observable) # subObservable) 57 | test "distinct" do 58 | liftEffect ((distinct observable) # subObservable) 59 | test "distinctUntilChanged" do 60 | liftEffect ((distinctUntilChanged observable) # subObservable) 61 | test "exhaust" do 62 | liftEffect ((exhaust higherOrder) # subObservable) 63 | test "exhaustMap" do 64 | liftEffect ((exhaustMap (\x -> observable3) observable) # subObservable) 65 | test "elementAt" do 66 | liftEffect ((elementAt 2 observable) # subObservable) 67 | test "every" do 68 | liftEffect ((every (_ > 3) observable # subObservable)) 69 | test "filter" do 70 | liftEffect ((filter (_ > 2) observable) # subObservable) 71 | test "groupBy" do 72 | liftEffect ((groupBy length observable2) # subObservable) 73 | test "ignoreElements" do 74 | liftEffect ((ignoreElements observable) # subObservable) 75 | test "isEmpty" do 76 | liftEffect ((isEmpty observable) # subObservable) 77 | test "first" do 78 | liftEffect ((first (const true) observable # subObservable)) 79 | test "last" do 80 | liftEffect ((last (const true) observable # subObservable)) 81 | test "map" do 82 | liftEffect ((map length observable2) # subObservable) 83 | test "mapTo" do 84 | liftEffect ((mapTo "A" observable) # subObservable) 85 | test "merge" do 86 | liftEffect ((merge observable observable3) # subObservable) 87 | test "mergeAll" do 88 | liftEffect ((mergeAll higherOrder) # subObservable) 89 | test "mergeMap" do 90 | liftEffect ((mergeMap observable (\a -> observable3)) # subObservable) 91 | test "mergeMapTo" do 92 | liftEffect ((mergeMapTo observable observable3) # subObservable) 93 | test "race" do 94 | liftEffect ((race [observable, observable3]) # subObservable) 95 | test "reduce" do 96 | liftEffect ((reduce (\acc cur -> acc) 0 observable) # subObservable) 97 | test "scan" do 98 | liftEffect ((scan (\acc cur -> acc) 0 observable) # subObservable) 99 | test "retry" do 100 | liftEffect ((retry 10 observable) # subObservable) 101 | test "sample" do 102 | liftEffect ((sample observable observable2) # subObservable) 103 | test "sampleTime" do 104 | liftEffect ((sampleTime 1000 observable) # subObservable) 105 | test "share" do 106 | liftEffect ((share observable) # subObservable) 107 | test "skip" do 108 | liftEffect ((skip 2 observable) # subObservable) 109 | test "skipUntil" do 110 | liftEffect ((skipUntil observable observable2) # subObservable) 111 | test "skipWhile" do 112 | liftEffect ((skipWhile (_ < 2) observable) # subObservable) 113 | test "startWith" do 114 | liftEffect ((startWith 0 observable) # subObservable) 115 | test "switchMap" do 116 | liftEffect ((switchMap (\x -> observable2) observable) # subObservable) 117 | test "switchMapTo" do 118 | liftEffect ((switchMapTo observable2 observable) # subObservable) 119 | test "take" do 120 | liftEffect ((take 3 observable) # subObservable) 121 | test "takeWhile" do 122 | liftEffect ((takeWhile (_ < 4) observable) # subObservable) 123 | test "takeUntil" do 124 | liftEffect ((takeUntil observable observable3) # subObservable) 125 | test "throttle" do 126 | liftEffect ((throttle (\x -> observable3) observable) # subObservable) 127 | test "throttleTime" do 128 | liftEffect ((throttleTime 200 observable) # subObservable) 129 | test "window" do 130 | liftEffect ((window observable observable2) # subObservable) 131 | test "windowCount" do 132 | liftEffect ((windowCount 1 1 observable) # subObservable) 133 | test "windowTime" do 134 | liftEffect ((windowTime 100 100 observable) # subObservable) 135 | test "withLatestFrom" do 136 | liftEffect ((withLatestFrom (\a b -> a) observable observable2) # subObservable) 137 | test "zip" do 138 | liftEffect ((zip [observable, observable3]) # subObservable) 139 | 140 | observable :: Observable Int 141 | observable = fromArray [1,2,3,4,5,6] 142 | 143 | observable2 :: Observable String 144 | observable2 = fromArray ["h","e","ll","o"] 145 | 146 | observable3 :: Observable Int 147 | observable3 = fromArray [7] 148 | 149 | higherOrder :: Observable (Observable String) 150 | higherOrder = just observable2 151 | 152 | subObservable :: forall a. Observable a -> Effect Unit 153 | subObservable obs = do 154 | sub <- extract (obs # subscribeNext noop) 155 | pure unit 156 | 157 | noop :: forall a. a -> Effect Unit 158 | noop a = pure unit 159 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/RxJS/Observable.js: -------------------------------------------------------------------------------- 1 | /* global exports */ 2 | "use strict"; 3 | 4 | // module RxJS.Observable 5 | import * as Rx from 'rxjs'; 6 | 7 | import * as RxOp from 'rxjs/operators'; 8 | import * as RxAjax from 'rxjs/ajax'; 9 | 10 | 11 | function removeEff(fn) { 12 | return function (a) { 13 | return fn(a)() 14 | } 15 | } 16 | 17 | /**** Scheduling ****/ 18 | 19 | export const observeOn_ = function (s) { 20 | return function (obs) { 21 | return RxOp.observeOn(obs, s); 22 | }; 23 | }; 24 | 25 | export const subscribeOn_ = function (s) { 26 | return function (obs) { 27 | return RxOp.subscribeOn(obs, s); 28 | }; 29 | }; 30 | 31 | /**** Subscription ****/ 32 | export const subscribe_ = function (sub) { 33 | return function (obs) { 34 | return function () { 35 | return obs.subscribe( 36 | function (val) { sub.next(val)(); }, 37 | function (err) { sub.error(err)(); }, 38 | function () { sub.complete()(); } 39 | ); 40 | }; 41 | }; 42 | }; 43 | 44 | export const subscribeNext_ = function (eff) { 45 | return function (obs) { 46 | return function () { 47 | return obs.subscribe( 48 | function (val) { eff(val)() } 49 | ); 50 | }; 51 | }; 52 | }; 53 | 54 | /**** Creation Operators ****/ 55 | 56 | export const ajax_ = function (req) { 57 | return function () { 58 | return RxAjax.ajax(req).pipe( 59 | RxOp.map(function (res) { 60 | var body = res.responseText || JSON.stringify(res.response) 61 | return { body: body, status: res.status, responseType: res.responseType } 62 | })) 63 | } 64 | }; 65 | 66 | export const ajaxWithBody_ = ajax_; 67 | export const _empty_ = Rx.EMPTY; 68 | export const fromArray_ = Rx.from; //Rx.Observable.from; 69 | export const fromEventImpl_ = Rx.fromEvent; 70 | export const interval_ = Rx.interval; 71 | export const just_ = Rx.of; 72 | export const never_ = Rx.NEVER; 73 | export const rangeImpl_ = Rx.range; 74 | export const throw_ = Rx.throw; 75 | export const timerImpl_ = Rx.timer; 76 | 77 | /**** Transformation Operators ****/ 78 | 79 | export const buffer_ = function (obs1) { 80 | return function (obs2) { 81 | return obs1.pipe(RxOp.buffer(obs2)); 82 | }; 83 | }; 84 | 85 | export const bufferCount_ = function (maxSize) { 86 | return function (startNewAt) { 87 | return function (obs) { 88 | return obs.pipe(RxOp.bufferCount(maxSize, startNewAt)); 89 | }; 90 | }; 91 | }; 92 | 93 | export const bufferTimeImpl_ = function (timespan, creationInterval, maxSize, obs) { 94 | return obs.pipe(RxOp.bufferTime(timespan, creationInterval, maxSize)); 95 | }; 96 | 97 | export const bufferToggleImpl_ = function (obs, openings, closingSelector) { 98 | return obs.pipe(RxOp.bufferToggle(openings, closingSelector)); 99 | }; 100 | 101 | export const bufferWhen_ = function (closing) { 102 | return function (obs) { 103 | return obs.pipe(RxOp.bufferWhen(closing)); 104 | }; 105 | }; 106 | 107 | export const concatMap_ = function (f) { 108 | return function (obs) { 109 | return obs.pipe(RxOp.concatMap(f)); 110 | }; 111 | }; 112 | 113 | export const exhaustMap_ = function (f) { 114 | return function (obs) { 115 | return obs.pipe(RxOp.exhaustMap(f)); 116 | }; 117 | }; 118 | 119 | export const expand_ = function (f) { 120 | return function (obs) { 121 | return obs.pipe(RxOp.expand(f)); 122 | }; 123 | }; 124 | 125 | export const share_ = function (obs) { 126 | return obs.pipe(RxOp.share()); 127 | }; 128 | 129 | export const groupBy_ = function (f) { 130 | return function (obs) { 131 | return obs.pipe(RxOp.groupBy(f)); 132 | }; 133 | }; 134 | 135 | export const _map_ = function (f) { 136 | return function (obs) { 137 | return obs.pipe(RxOp.map(f)); 138 | }; 139 | }; 140 | 141 | export const mapTo_ = function (val) { 142 | return function (obs1) { 143 | return obs1.pipe(RxOp.mapTo(val)); 144 | }; 145 | }; 146 | 147 | export const mergeMap_ = function (obs) { 148 | return function (f) { 149 | return obs.pipe(RxOp.mergeMap(f)); 150 | }; 151 | }; 152 | 153 | export const mergeMapTo_ = function (obs1) { 154 | return function (obs2) { 155 | return obs1.pipe(RxOp.mergeMapTo(obs2)); 156 | }; 157 | }; 158 | 159 | export const pairwiseImpl_ = function (obs) { 160 | return obs.pipe(RxOp.pairwise()); 161 | }; 162 | 163 | export const partitionImpl_ = function (pred) { 164 | return function (obs) { 165 | return obs.pipe(RxOp.partition(pred)); 166 | }; 167 | }; 168 | 169 | export const scan_ = function (f) { 170 | return function (seed) { 171 | return function (ob) { 172 | return ob.pipe(RxOp.scan(function (acc, value) { 173 | return f(value)(acc); 174 | }, seed)); 175 | }; 176 | }; 177 | }; 178 | 179 | export const switchMap_ = function (f) { 180 | return function (obs) { 181 | return obs.pipe(RxOp.switchMap(f)); 182 | }; 183 | }; 184 | 185 | export const switchMapTo_ = function (obs2) { 186 | return function (obs1) { 187 | return obs1.pipe(RxOp.switchMapTo(obs2)); 188 | }; 189 | }; 190 | 191 | export const window_ = function (obs2) { 192 | return function (obs1) { 193 | return obs1.pipe(RxOp.window(obs2)); 194 | }; 195 | }; 196 | 197 | export const windowCount_ = function (maxSize) { 198 | return function (startNewAt) { 199 | return function (obs) { 200 | return obs.pipe(RxOp.windowCount(maxSize, startNewAt)); 201 | }; 202 | }; 203 | }; 204 | 205 | export const windowTime_ = function (timeSpan) { 206 | return function (startNewAt) { 207 | return function (obs) { 208 | return obs.pipe(RxOp.windowTime(timeSpan, startNewAt)); 209 | }; 210 | }; 211 | }; 212 | 213 | /**** Filtering Operators ****/ 214 | 215 | export const audit_ = function (f) { 216 | return function (obs) { 217 | return obs.pipe(RxOp.audit(f)); 218 | }; 219 | }; 220 | 221 | export const auditTime_ = function (ms) { 222 | return function (obs) { 223 | return obs.pipe(RxOp.auditTime(ms)); 224 | }; 225 | }; 226 | 227 | export const debounce_ = function (f) { 228 | return function (ob) { 229 | return ob.pipe(RxOp.debounce(f)); 230 | }; 231 | }; 232 | 233 | export const debounceTime_ = function (ms) { 234 | return function (obs) { 235 | return obs.pipe(RxOp.debounceTime(ms)); 236 | }; 237 | }; 238 | 239 | export const distinct_ = function (ob) { 240 | return ob.pipe(RxOp.distinct()); 241 | }; 242 | 243 | export const distinctUntilChanged_ = function (ob) { 244 | return ob.pipe(RxOp.distinctUntilChanged()); 245 | }; 246 | 247 | export const elementAt_ = function (i) { 248 | return function (obs) { 249 | return obs.pipe(RxOp.elementAt(i)); 250 | }; 251 | }; 252 | 253 | export const filter_ = function (p) { 254 | return function (ob) { 255 | return ob.pipe(RxOp.filter(p)); 256 | }; 257 | }; 258 | 259 | export const first_ = function (p) { 260 | return function (ob) { 261 | return ob.pipe(RxOp.first(p)); 262 | }; 263 | }; 264 | 265 | export const ignoreElements_ = function (obs) { 266 | return obs.pipe(RxOp.ignoreElements()); 267 | }; 268 | 269 | export const last_ = function (p) { 270 | return function (ob) { 271 | return ob.pipe(RxOp.last(p)); 272 | }; 273 | }; 274 | 275 | export const sample_ = function (obs2) { 276 | return function (obs1) { 277 | return obs1.pipe(RxOp.sample(obs2)); 278 | }; 279 | }; 280 | 281 | export const sampleTime_ = function (ms) { 282 | return function (obs) { 283 | return obs.pipe(RxOp.sampleTime(ms)); 284 | }; 285 | }; 286 | 287 | export const skip_ = function (n) { 288 | return function (obs) { 289 | return obs.pipe(RxOp.skip(n)); 290 | }; 291 | }; 292 | 293 | export const skipUntil_ = function (obs2) { 294 | return function (obs1) { 295 | return obs1.pipe(RxOp.skipUntil(obs2)); 296 | }; 297 | }; 298 | 299 | export const skipWhile_ = function (p) { 300 | return function (obs) { 301 | return obs.pipe(RxOp.skipWhile(p)); 302 | }; 303 | }; 304 | 305 | export const take_ = function (n) { 306 | return function (ob) { 307 | return ob.pipe(RxOp.take(n)); 308 | }; 309 | }; 310 | 311 | export const takeUntil_ = function (other) { 312 | return function (ob) { 313 | return ob.pipe(RxOp.takeUntil(other)); 314 | }; 315 | }; 316 | 317 | export const takeWhile_ = function (obs2) { 318 | return function (obs1) { 319 | return obs1.pipe(RxOp.takeWhile(obs2)); 320 | }; 321 | }; 322 | 323 | export const throttle_ = function (f) { 324 | return function (obs) { 325 | return obs.pipe(RxOp.throttle(f)); 326 | }; 327 | }; 328 | 329 | export const throttleTime_ = function (ms) { 330 | return function (obs) { 331 | return obs.pipe(RxOp.throttleTime(ms)); 332 | }; 333 | }; 334 | 335 | /**** Combination Operators ****/ 336 | 337 | export const combineLatest_ = function (f) { 338 | return function (ob1) { 339 | return function (ob2) { 340 | return Rx.combineLatest(ob1, ob2, function (x, y) { 341 | return f(x)(y); 342 | }); 343 | }; 344 | }; 345 | }; 346 | 347 | export const combineLatest3_ = function (f) { 348 | return function (obs1) { 349 | return function (obs2) { 350 | return function (obs3) { 351 | return Rx.combineLatest(obs1, obs2, obs3, function (x, y, z) { 352 | return f(x)(y)(z); 353 | }); 354 | }; 355 | }; 356 | }; 357 | }; 358 | 359 | export const concat_ = function (obs1) { 360 | return function (obs2) { 361 | return Rx.concat(obs1, obs2); 362 | }; 363 | }; 364 | 365 | export const concatAll_ = function (obsobs) { 366 | return obsobs.pipe(RxOp.concatAll()); 367 | }; 368 | 369 | export const exhaust_ = function (obsobs) { 370 | return obsobs.pipe(RxOp.exhaust()); 371 | }; 372 | 373 | export const merge_ = function (ob) { 374 | return function (other) { 375 | return ob.pipe(RxOp.merge(other)); 376 | }; 377 | }; 378 | 379 | export const mergeAll_ = function (obsobs) { 380 | return obsobs.pipe(RxOp.mergeAll()); 381 | }; 382 | 383 | export const race_ = function (arrOfObs) { 384 | return Rx.race.apply(this, arrOfObs); 385 | }; 386 | 387 | export const startWith_ = function (start) { 388 | return function (ob) { 389 | return ob.pipe(RxOp.startWith(start)); 390 | }; 391 | }; 392 | 393 | export const withLatestFrom_ = function (f) { 394 | return function (ob2) { 395 | return function (ob1) { 396 | return ob1.pipe(RxOp.withLatestFrom(ob2, function (x, y) { 397 | return f(x)(y); 398 | })) 399 | }; 400 | }; 401 | }; 402 | 403 | export const zip_ = function (arrOfObs) { 404 | return Rx.zip.apply(this, arrOfObs); 405 | }; 406 | 407 | /**** Error Handling Operators ****/ 408 | 409 | export const catch_ = function (obs) { 410 | return function (f) { 411 | return obs.pipe(RxOp.catchError(f)); 412 | }; 413 | }; 414 | 415 | export const retry_ = function (nTimes) { 416 | return function (obs) { 417 | return obs.pipe(RxOp.retry(nTimes)); 418 | }; 419 | }; 420 | 421 | /**** Utility Operators ****/ 422 | 423 | export const delay_ = function (ms) { 424 | return function (ob) { 425 | return ob.pipe(RxOp.delay(ms)); 426 | }; 427 | }; 428 | 429 | export const delayWhen_ = function (f) { 430 | return function (obs1) { 431 | return obs1.pipe(RxOp.delayWhen(f)); 432 | }; 433 | }; 434 | 435 | export const materializeImpl = function (ob, Next, Error, Complete) { 436 | return ob.pipe( 437 | RxOp.materialize(), 438 | RxOp.map(function (x) { 439 | switch (x.kind) { 440 | case 'N': return Next(x.value); 441 | case 'E': return Error(x.error); 442 | case 'C': return Complete; 443 | } 444 | })); 445 | }; 446 | 447 | export const create_ = function (subscriberToEff) { 448 | return function () { 449 | return Rx.Observable.create(subscriberToObserverFn(subscriberToEff)) 450 | } 451 | }; 452 | 453 | function subscriberToObserverFn(subscriberFn) { 454 | return removeEff(function (observer) { 455 | var subscriber = observerToSubscriber(observer) 456 | return subscriberFn(subscriber) 457 | }) 458 | } 459 | 460 | function observerToSubscriber(observer) { 461 | return { 462 | next: function (a) { 463 | return function () { observer.next(a) } 464 | }, 465 | error: function (e) { 466 | return function () { observer.error(e) } 467 | }, 468 | completed: function () { 469 | return function () { observer.completed() } 470 | } 471 | 472 | } 473 | } 474 | 475 | export const dematerialize_ = function (ob) { 476 | return ob.pipe( 477 | RxOp.map(function (a) { 478 | switch (a.constructor.name) { 479 | case "OnNext": return Rx.Notification.createNext(a.value0); 480 | case "OnError": return Rx.Notification.createError(a.value0); 481 | case "OnComplete": return Rx.Notification.createComplete(); 482 | } 483 | }), 484 | dematerialize()); 485 | }; 486 | 487 | export const toArray_ = function (obs) { 488 | return obs.pipe(RxOp.toArray()); 489 | }; 490 | 491 | /**** Conditional and Boolean Operators ****/ 492 | 493 | export const defaultIfEmpty_ = function (val) { 494 | return function (obs) { 495 | return obs.pipe(RxOp.defaultIfEmpty(val)); 496 | }; 497 | }; 498 | 499 | export const every_ = function (pred) { 500 | return function (obs) { 501 | return obs.pipe(RxOp.every(pred)); 502 | }; 503 | }; 504 | 505 | export const isEmpty_ = function (obs) { 506 | return obs.pipe(RxOp.isEmpty()); 507 | }; 508 | 509 | /**** Aggregate Operators ****/ 510 | 511 | export const count_ = function (obs) { 512 | return obs.pipe(RxOp.count()); 513 | }; 514 | 515 | export const reduce_ = function (f) { 516 | return function (seed) { 517 | return function (ob) { 518 | return ob.pipe(RxOp.reduce(function (x, y) { 519 | return f(x)(y); 520 | }, seed)); 521 | }; 522 | }; 523 | }; 524 | 525 | /**** Helpers ****/ 526 | 527 | export const unwrap_ = function (obs) { 528 | return function () { 529 | return obs.pipe(RxOp.map(function (eff) { 530 | return eff(); 531 | })); 532 | }; 533 | }; 534 | -------------------------------------------------------------------------------- /src/RxJS/Observable.purs: -------------------------------------------------------------------------------- 1 | module RxJS.Observable 2 | ( ObservableT(..) 3 | , Observable 4 | , ObservableImpl 5 | , observeOn 6 | , subscribeOn 7 | , subscribe 8 | , subscribeNext 9 | , fromArray 10 | , fromEvent 11 | , interval 12 | , just 13 | , create 14 | , every 15 | , never 16 | , range 17 | , throw 18 | , timer 19 | , buffer 20 | , bufferCount 21 | , bufferTime 22 | , bufferWhen 23 | , concatMap 24 | , exhaustMap 25 | , expand 26 | , groupBy 27 | , mapTo 28 | , mergeMap 29 | , mergeMapTo 30 | , pairwise 31 | , partition 32 | , scan 33 | , scanM 34 | , switchMap 35 | , switchMapTo 36 | , window 37 | , windowCount 38 | , windowTime 39 | , audit 40 | , ajax 41 | , ajaxUrl 42 | , auditTime 43 | , debounce 44 | , debounceTime 45 | , distinct 46 | , distinctUntilChanged 47 | , elementAt 48 | , filter 49 | , ignoreElements 50 | , first 51 | , last 52 | , sample 53 | , isEmpty 54 | , sampleTime 55 | , share 56 | , skip 57 | , skipUntil 58 | , skipWhile 59 | , take 60 | , takeUntil 61 | , takeWhile 62 | , throttle 63 | , throttleTime 64 | , combineLatest 65 | , combineLatest3 66 | , concat 67 | , concatAll 68 | , exhaust 69 | , merge 70 | , mergeAll 71 | , race 72 | , startWith 73 | , startWithMany 74 | , withLatestFrom 75 | , zip 76 | , catch 77 | , retry 78 | , defaultIfEmpty 79 | , delay 80 | , delayWhen 81 | , dematerialize 82 | , materialize 83 | , toArray 84 | , count 85 | , reduce 86 | , runObservableT 87 | , unwrapEff 88 | , Response 89 | , Request 90 | ) 91 | where 92 | 93 | import Effect.Uncurried (EffectFn2, runEffectFn2) 94 | import Control.Alt (class Alt) 95 | import Control.Alternative (class Alternative) 96 | import Control.Comonad (class Comonad, extract) 97 | import Effect (Effect) 98 | import Effect.Exception (Error) 99 | import Effect.Unsafe (unsafePerformEffect) 100 | import Control.Monad.Error.Class (class MonadThrow, class MonadError) 101 | import Control.MonadPlus (class MonadPlus) 102 | import Control.Plus (class Plus) 103 | import Web.Event.Event (Event, EventType(..)) 104 | import Web.Event.EventTarget (EventTarget) 105 | import Data.Array.Partial (head, last) as Array 106 | import Data.Foldable (foldr, class Foldable) 107 | import Data.Function.Uncurried (Fn2, Fn3, Fn4, runFn2, runFn3, runFn4) 108 | import Data.Identity (Identity) 109 | import Data.Monoid (class Monoid) 110 | import Foreign.Object (Object, empty) 111 | import Data.Tuple (Tuple(..), fst, snd) 112 | import Partial.Unsafe (unsafePartial) 113 | import Prelude (class Applicative, class Apply, class Bind, class Functor, class Monad, class Semigroup, identity, map, pure, (#), ($), (<$>), (<*>), (<<<), (>>=), (>>>)) 114 | import RxJS.Notification (Notification(OnComplete, OnError, OnNext)) 115 | import RxJS.Scheduler (Scheduler) 116 | import RxJS.Subscriber (Subscriber) 117 | import RxJS.Subscription (Subscription) 118 | 119 | foreign import data ObservableImpl :: Type -> Type 120 | 121 | instance monoidObservableImpl :: Monoid (ObservableImpl a) where 122 | mempty = _empty_ 123 | 124 | instance functorObservableImpl :: Functor ObservableImpl where 125 | map = _map_ 126 | 127 | instance applyObservableImpl :: Apply ObservableImpl where 128 | apply = combineLatest_ identity 129 | 130 | instance applicativeObservableImpl :: Applicative ObservableImpl where 131 | pure = just_ 132 | 133 | instance bindObservableImpl :: Bind ObservableImpl where 134 | bind = mergeMap_ 135 | 136 | instance monadObservableImpl :: Monad ObservableImpl 137 | 138 | instance semigroupObservableImpl :: Semigroup (ObservableImpl a) where 139 | append = merge_ 140 | 141 | instance altObservableImpl :: Alt ObservableImpl where 142 | alt = merge_ 143 | 144 | instance plusObservableImpl :: Plus ObservableImpl where 145 | empty = _empty_ 146 | 147 | instance alternativeObservableImpl :: Alternative ObservableImpl 148 | 149 | instance monadPlusObservableImpl :: MonadPlus ObservableImpl 150 | 151 | instance monadErrorObservableImpl :: MonadError Error ObservableImpl where 152 | catchError = catch_ 153 | 154 | instance monadThrowObservableImpl :: MonadThrow Error ObservableImpl where 155 | throwError = throw_ 156 | 157 | 158 | foreign import observeOn_ :: forall a. Scheduler -> ObservableImpl a -> ObservableImpl a 159 | 160 | foreign import subscribeOn_ :: forall a. Scheduler -> ObservableImpl a -> ObservableImpl a 161 | 162 | -- Subscription 163 | 164 | foreign import subscribe_ :: forall a. Subscriber a -> ObservableImpl a -> Effect Subscription 165 | 166 | foreign import subscribeNext_ :: forall a u. (a -> Effect u) -> ObservableImpl a -> Effect Subscription 167 | 168 | 169 | -- Creation Operators 170 | 171 | 172 | type Response = 173 | { body :: String 174 | , status :: Int 175 | , responseType :: String 176 | } 177 | 178 | type Request = 179 | { url :: String 180 | , body :: String 181 | , timeout :: Int 182 | , headers :: Object String 183 | , crossDomain :: Boolean 184 | , responseType :: String 185 | , method :: String 186 | } 187 | 188 | -- | Create a Request object with a given URL, Body and Method in that order 189 | requestWithBody :: String -> String -> String -> Request 190 | requestWithBody url body method = 191 | { url : url 192 | , body : body 193 | , timeout : 0 194 | , headers : empty 195 | , crossDomain : false 196 | , responseType : "" 197 | , method : method 198 | } 199 | 200 | 201 | foreign import ajax_ :: String -> Effect (ObservableImpl Response) 202 | foreign import ajaxWithBody_ :: Request -> Effect (ObservableImpl Response) 203 | foreign import _empty_ :: forall a. ObservableImpl a 204 | foreign import fromArray_ :: forall a. Array a -> ObservableImpl a 205 | foreign import fromEventImpl_ :: EffectFn2 EventTarget String (ObservableImpl Event) 206 | foreign import interval_ :: Int -> ObservableImpl Int 207 | foreign import just_ :: forall a. a -> ObservableImpl a 208 | foreign import create_ :: forall a u. (Subscriber a -> Effect u) -> Effect (ObservableImpl a) 209 | foreign import never_ :: forall a. ObservableImpl a 210 | foreign import rangeImpl_ :: Fn2 Int Int (ObservableImpl Int) 211 | foreign import throw_ :: forall a. Error -> ObservableImpl a 212 | foreign import timerImpl_ :: Fn2 Int Int (ObservableImpl Int) 213 | foreign import buffer_ :: forall a b. ObservableImpl b -> ObservableImpl a -> ObservableImpl (Array a) 214 | foreign import bufferCount_ :: forall a. Int -> Int -> ObservableImpl a -> ObservableImpl (Array a) 215 | foreign import bufferTimeImpl_ :: forall a. Fn4 Int Int Int (ObservableImpl a) (ObservableImpl (Array a)) 216 | foreign import bufferToggleImpl_ 217 | :: forall a b c. Fn3 (ObservableImpl a) (ObservableImpl b) (b -> ObservableImpl c) (ObservableImpl (Array a)) 218 | foreign import bufferWhen_ :: forall a b. (a -> ObservableImpl b) -> ObservableImpl a -> ObservableImpl (Array a) 219 | foreign import concatMap_ :: forall a b. (a -> ObservableImpl b) -> ObservableImpl a -> ObservableImpl b 220 | foreign import exhaustMap_ :: forall a b. (a -> ObservableImpl b) -> ObservableImpl a -> ObservableImpl b 221 | foreign import expand_ :: forall a. (a -> ObservableImpl a) -> ObservableImpl a -> ObservableImpl a 222 | foreign import groupBy_ :: forall a b. (a -> b) -> ObservableImpl a -> ObservableImpl (ObservableImpl a) 223 | foreign import _map_ :: forall a b. (a -> b) -> ObservableImpl a -> ObservableImpl b 224 | foreign import mapTo_ :: forall a b. b -> ObservableImpl a -> ObservableImpl b 225 | foreign import mergeMap_ :: forall a b. ObservableImpl a -> (a -> ObservableImpl b) -> ObservableImpl b 226 | foreign import mergeMapTo_ :: forall a b. ObservableImpl a -> ObservableImpl b -> ObservableImpl b 227 | foreign import pairwiseImpl_ :: forall a. ObservableImpl a -> ObservableImpl (Array a) 228 | foreign import partitionImpl_ :: forall a. (a -> Boolean) -> ObservableImpl a -> Array (ObservableImpl a) 229 | foreign import scan_ :: forall a b. (a -> b -> b) -> b -> ObservableImpl a -> ObservableImpl b 230 | foreign import switchMap_ :: forall a b. (a -> ObservableImpl b) -> ObservableImpl a -> ObservableImpl b 231 | foreign import switchMapTo_ :: forall a b. ObservableImpl b -> ObservableImpl a -> ObservableImpl b 232 | foreign import window_ :: forall a b. ObservableImpl b -> ObservableImpl a -> ObservableImpl (ObservableImpl a) 233 | foreign import windowCount_ :: forall a. Int -> Int -> ObservableImpl a -> ObservableImpl (ObservableImpl a) 234 | foreign import windowTime_ :: forall a. Int -> Int -> ObservableImpl a -> ObservableImpl (ObservableImpl a) 235 | foreign import audit_ :: forall a b. (a -> ObservableImpl b) -> ObservableImpl a -> ObservableImpl a 236 | foreign import auditTime_ :: forall a. Int -> ObservableImpl a -> ObservableImpl a 237 | foreign import debounce_ :: forall a. (a -> ObservableImpl Int) -> ObservableImpl a -> ObservableImpl a 238 | foreign import debounceTime_ :: forall a. Int -> ObservableImpl a -> ObservableImpl a 239 | foreign import distinct_ :: forall a. ObservableImpl a -> ObservableImpl a 240 | foreign import distinctUntilChanged_ :: forall a. ObservableImpl a -> ObservableImpl a 241 | foreign import elementAt_ :: forall a. Int -> ObservableImpl a -> ObservableImpl a 242 | foreign import filter_ :: forall a. (a -> Boolean) -> ObservableImpl a -> ObservableImpl a 243 | foreign import ignoreElements_ :: forall a. ObservableImpl a -> ObservableImpl a 244 | foreign import last_ :: forall a. (a -> Boolean) -> ObservableImpl a -> ObservableImpl a 245 | foreign import sample_ :: forall a b. ObservableImpl b -> ObservableImpl a -> ObservableImpl a 246 | foreign import sampleTime_ :: forall a. Int -> ObservableImpl a -> ObservableImpl a 247 | foreign import skip_ :: forall a. Int -> ObservableImpl a -> ObservableImpl a 248 | foreign import skipUntil_ :: forall a b. ObservableImpl b -> ObservableImpl a -> ObservableImpl a 249 | foreign import skipWhile_ :: forall a. (a -> Boolean) -> ObservableImpl a -> ObservableImpl a 250 | foreign import take_ :: forall a. Int -> ObservableImpl a -> ObservableImpl a 251 | foreign import takeUntil_ :: forall a b. ObservableImpl b -> ObservableImpl a -> ObservableImpl a 252 | foreign import takeWhile_ :: forall a. (a -> Boolean) -> ObservableImpl a -> ObservableImpl a 253 | foreign import throttle_ :: forall a b. (a -> ObservableImpl b) -> ObservableImpl a -> ObservableImpl a 254 | foreign import throttleTime_ :: forall a. Int -> ObservableImpl a -> ObservableImpl a 255 | foreign import combineLatest_ 256 | :: forall a b c. (a -> b -> c) -> ObservableImpl a -> ObservableImpl b -> ObservableImpl c 257 | foreign import combineLatest3_ 258 | :: forall a b c d. (a -> b -> c -> d) -> ObservableImpl a -> ObservableImpl b -> ObservableImpl c -> ObservableImpl d 259 | foreign import concat_ :: forall a. ObservableImpl a -> ObservableImpl a -> ObservableImpl a 260 | foreign import concatAll_ :: forall a. ObservableImpl (ObservableImpl a) -> ObservableImpl a 261 | foreign import exhaust_ :: forall a. ObservableImpl (ObservableImpl a) -> ObservableImpl a 262 | foreign import merge_ :: forall a. ObservableImpl a -> ObservableImpl a -> ObservableImpl a 263 | foreign import mergeAll_ :: forall a. ObservableImpl (ObservableImpl a) -> ObservableImpl a 264 | foreign import race_ :: forall a. Array (ObservableImpl a) -> ObservableImpl a 265 | foreign import startWith_ :: forall a. a -> ObservableImpl a -> ObservableImpl a 266 | foreign import withLatestFrom_ 267 | :: forall a b c. (a -> b -> c) -> ObservableImpl b -> ObservableImpl a -> ObservableImpl c 268 | foreign import zip_ :: forall a. Array (ObservableImpl a) -> ObservableImpl (Array a) 269 | foreign import catch_ :: forall a. ObservableImpl a -> (Error -> ObservableImpl a) -> ObservableImpl a 270 | foreign import retry_ :: forall a. Int -> ObservableImpl a -> ObservableImpl a 271 | foreign import delay_ :: forall a. Int -> ObservableImpl a -> ObservableImpl a 272 | foreign import delayWhen_ :: forall a b. (a -> ObservableImpl b) -> ObservableImpl a -> ObservableImpl a 273 | foreign import dematerialize_ :: forall a. ObservableImpl (Notification a) -> ObservableImpl a 274 | foreign import materializeImpl 275 | :: forall a. 276 | Fn4 277 | (ObservableImpl a) 278 | (a -> Notification a) 279 | (Error -> Notification a) 280 | (Notification a) 281 | (ObservableImpl (Notification a)) 282 | foreign import toArray_ :: forall a. ObservableImpl a -> ObservableImpl (Array a) 283 | foreign import defaultIfEmpty_ :: forall a. a -> ObservableImpl a -> ObservableImpl a 284 | foreign import every_ :: forall a. (a -> Boolean) -> ObservableImpl a -> ObservableImpl Boolean 285 | foreign import isEmpty_ :: forall a. ObservableImpl a -> ObservableImpl Boolean 286 | foreign import share_ :: forall a. ObservableImpl a -> ObservableImpl a 287 | foreign import first_ :: forall a. (a -> Boolean) -> ObservableImpl a -> ObservableImpl a 288 | foreign import count_ :: forall a. ObservableImpl a -> ObservableImpl Int 289 | foreign import reduce_ :: forall a b. (a -> b -> b) -> b -> ObservableImpl a -> ObservableImpl b 290 | foreign import unwrap_ :: forall a. ObservableImpl (Effect a) -> Effect (ObservableImpl a) 291 | 292 | --- ObservableT 293 | 294 | newtype ObservableT m a = ObservableT (m (ObservableImpl a)) 295 | type Observable a = ObservableT Identity a 296 | 297 | liftT :: forall a. ObservableImpl a -> Observable a 298 | liftT = ObservableT <<< pure 299 | 300 | runObservableT :: forall m a. ObservableT m a -> m (ObservableImpl a) 301 | runObservableT (ObservableT m) = m 302 | 303 | 304 | instance functorObservableT :: (Functor f) => Functor (ObservableT f) where 305 | map f (ObservableT fo) = 306 | ObservableT (map (map f) fo) 307 | 308 | instance combineInnerervableT :: Apply f => Apply (ObservableT f) where 309 | apply = combineLatest identity 310 | 311 | instance applicativeObservableT :: Applicative f => Applicative (ObservableT f) where 312 | pure = just 313 | 314 | instance semigroupObservableT :: Apply f => Semigroup (ObservableT f a) where 315 | append = merge 316 | 317 | instance monoidObservableT :: Applicative f => Monoid (ObservableT f a) where 318 | mempty = _empty 319 | 320 | instance altObservableT :: Apply f => Alt (ObservableT f) where 321 | alt = merge 322 | 323 | instance plusObservableT :: Applicative f => Plus (ObservableT f) where 324 | empty = _empty 325 | 326 | instance bindObservableT :: Monad m => Bind (ObservableT m) where 327 | bind = mergeMap 328 | 329 | instance monadObservableT :: Monad m => Monad (ObservableT m) 330 | 331 | instance alternativeObservableT :: Monad m => Alternative (ObservableT m) 332 | 333 | instance monadPlusObservableT :: Monad m => MonadPlus (ObservableT m) 334 | 335 | 336 | combineInner :: forall a b c f. Apply f => (ObservableImpl a -> ObservableImpl b -> ObservableImpl c) 337 | -> ObservableT f a 338 | -> ObservableT f b 339 | -> ObservableT f c 340 | combineInner f (ObservableT fa) (ObservableT fb) = 341 | let fc = f <$> fa <*> fb 342 | in ObservableT fc 343 | 344 | combineInner3 :: forall a b c d f. Apply f => (ObservableImpl a -> ObservableImpl b -> ObservableImpl c -> ObservableImpl d) 345 | -> ObservableT f a 346 | -> ObservableT f b 347 | -> ObservableT f c 348 | -> ObservableT f d 349 | combineInner3 f (ObservableT fa) (ObservableT fb) (ObservableT fc) = 350 | let fd = f <$> fa <*> fb <*> fc 351 | in ObservableT fd 352 | 353 | mapInner :: forall a b f. Functor f => (ObservableImpl a -> ObservableImpl b) -> ObservableT f a -> ObservableT f b 354 | mapInner f (ObservableT fo) = ObservableT (map f fo) 355 | 356 | 357 | 358 | -- Public api: 359 | 360 | 361 | -- | An Observable of projected values from the most recent values from each input Observable. 362 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/combineLatest.png) 363 | combineLatest3 :: forall a b c d f. Apply f => 364 | (a -> b -> c -> d) -> ObservableT f a -> ObservableT f b -> ObservableT f c -> ObservableT f d 365 | combineLatest3 selector = combineInner3 (combineLatest3_ selector) 366 | 367 | -- | An Observable of projected values from the most recent values from each input 368 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/combineLatest.png) 369 | combineLatest :: forall a b c f. Apply f => (a -> b -> c) -> ObservableT f a -> ObservableT f b -> ObservableT f c 370 | combineLatest selector = combineInner (combineLatest_ selector) 371 | 372 | -- | Creates an output ObservableImpl which concurrently emits all values from each input ObservableImpl. 373 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/merge.png) 374 | merge :: forall a f. Apply f => ObservableT f a -> ObservableT f a -> ObservableT f a 375 | merge = combineInner merge_ 376 | 377 | 378 | fromObservable :: forall a f. Applicative f => ObservableImpl a -> ObservableT f a 379 | fromObservable o = ObservableT (pure o) 380 | 381 | liftF :: forall a f. Applicative f => f a -> ObservableT f a 382 | liftF f = ObservableT (map pure f) 383 | 384 | 385 | 386 | -- | Creates an ObservableImpl that immediately sends an error notification. 387 | throw :: forall a f. Applicative f => Error -> ObservableT f a 388 | throw err = ObservableT (pure (throw_ err)) 389 | 390 | 391 | -- | Creates an ObservableImpl that emits the value specify, 392 | -- | and then emits a complete notification. An alias for `of`. 393 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/from.png) 394 | just :: forall a f. Applicative f => a -> ObservableT f a 395 | just a = ObservableT (pure (just_ a)) 396 | 397 | ajaxUrl :: String -> ObservableT (Effect) Response 398 | ajaxUrl url = 399 | ObservableT (ajax_ url) 400 | 401 | ajax :: Request -> ObservableT (Effect) Response 402 | ajax req = 403 | ObservableT (ajaxWithBody_ req) 404 | 405 | _empty :: forall a f. Applicative f => ObservableT f a 406 | _empty = ObservableT (pure _empty_) 407 | 408 | -- | Creates an ObservableImpl that emits no items. Subscriptions it must be 409 | -- | disposed manually. 410 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/never.png) 411 | never :: forall a f. Applicative f => ObservableT f a 412 | never = ObservableT (pure never_) 413 | 414 | -- | Creates an ObservableImpl from an Array. 415 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/from.png) 416 | fromArray :: forall a f. Applicative f => Array a -> ObservableT f a 417 | fromArray arr = ObservableT (pure (fromArray_ arr)) 418 | 419 | -- | Creates an ObservableImpl that emits events of the specified type coming from the given event target. 420 | fromEvent :: EventTarget -> EventType -> ObservableT Effect Event 421 | fromEvent target (EventType str) = ObservableT $ runEffectFn2 fromEventImpl_ target str 422 | 423 | -- | Returns an ObservableImpl that emits an infinite sequence of ascending 424 | -- | integers, with a constant interval of time of your choosing between those 425 | -- | emissions. 426 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/interval.png) 427 | interval :: forall f. Applicative f => Int -> ObservableT f Int 428 | interval period = ObservableT (pure (interval_ period)) 429 | 430 | -- | The range operator emits a range of sequential integers, in order, where 431 | -- | you select the start of the range and its length 432 | -- | ![marble diagram](http://reactivex.io/rxjs/img/range.png) 433 | range :: forall f. Applicative f => Int -> Int -> ObservableT f Int 434 | range r l = ObservableT (pure (runFn2 rangeImpl_ r l)) 435 | 436 | -- | Creates an Observable that, upon subscription, emits and infinite sequence of ascending integers, 437 | -- | after a specified delay, every specified period. Delay and period are in 438 | -- | milliseconds. 439 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/timer.png) 440 | timer :: forall f. Applicative f => Int -> Int -> ObservableT f Int 441 | timer dly period = ObservableT (pure (runFn2 timerImpl_ dly period)) 442 | 443 | 444 | create :: forall a u. (Subscriber a -> Effect u) -> ObservableT (Effect) a 445 | create fn = ObservableT (create_ fn) 446 | 447 | -- | Collects values from the first Observable into an Array, and emits that array only when 448 | -- | second Observable emits. 449 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/buffer1.png) 450 | buffer :: forall a b f. Apply f => ObservableT f b -> ObservableT f a -> ObservableT f (Array a) 451 | buffer = combineInner buffer_ 452 | 453 | -- | Collects values from the past as an array, emits that array when 454 | -- | its size (arg1) reaches the specified buffer size, and starts a new buffer. 455 | -- | The new buffer starts with nth (arg2) element of the Observable counting 456 | -- | from the beginning of the *last* buffer. 457 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/buffer1.png) 458 | bufferCount :: forall a f. Functor f => Int -> Int -> ObservableT f a -> ObservableT f (Array a) 459 | bufferCount size offset = mapInner (bufferCount_ size offset) 460 | 461 | -- | Collects values from the past as an array, and emits those arrays 462 | -- | periodically in time. The first argument is how long to fill the buffer. 463 | -- | The second argument is specifies when to open the next buffer following an 464 | -- | emission. The third argument is the maximum size of any buffer. 465 | bufferTime :: forall a f. Functor f => Int -> Int -> Int -> (ObservableT f a) -> (ObservableT f (Array a)) 466 | bufferTime time opens size = mapInner (runFn4 bufferTimeImpl_ time opens size) 467 | 468 | -- | Emits the given constant value on the output Observable every time 469 | -- | the source Observable emits a value. 470 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/map.png) 471 | mapTo :: forall a b f. Functor f => b -> ObservableT f a -> ObservableT f b 472 | mapTo b = mapInner (mapTo_ b) 473 | 474 | -- | Puts the current value and previous value together as an array, and emits that. 475 | -- | ![marble diagram](http://reactivex.io/rxjs/img/pairwise.png) 476 | pairwise :: forall a f. Functor f => ObservableT f a -> ObservableT f (Tuple a a) 477 | pairwise src = 478 | let arrays = mapInner pairwiseImpl_ src 479 | toTuple arr = unsafePartial (Tuple (Array.head arr) (Array.last arr)) 480 | in map toTuple arrays 481 | 482 | -- | Given a predicate function (arg1), and an Observable (arg2), it outputs a 483 | -- | two element array of partitioned values 484 | -- | (i.e., [ Observable valuesThatPassPredicate, Observable valuesThatFailPredicate ]). 485 | -- | ![marble diagram](http://reactivex.io/rxjs/img/partition.png) 486 | partition :: forall a f. Applicative f => (a -> Boolean) -> ObservableT f a -> Tuple (ObservableT f a) (ObservableT f a) 487 | partition predicate (ObservableT src) = 488 | let toTuple arr = unsafePartial (Tuple (Array.head arr) (Array.last arr)) 489 | partitioned = map ((partitionImpl_ predicate) >>> toTuple) src 490 | firstT = ObservableT (map fst partitioned) 491 | secondT = ObservableT (map snd partitioned) 492 | in Tuple firstT secondT 493 | 494 | 495 | -- | Maps each value to an Observable, then flattens all of these Observables 496 | -- | using mergeAll. It's just monadic `bind`. 497 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/flatMap.c.png) 498 | mergeMap :: forall a b m. Monad m => ObservableT m a -> (a -> ObservableT m b) -> ObservableT m b 499 | mergeMap ma f = join_ (map f ma) 500 | 501 | -- | Maps each value of the ObservableImpl (arg1) to the same inner ObservableImpl (arg2), 502 | -- | then flattens the result. 503 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/flatMap.c.png) 504 | mergeMapTo :: forall a b m. Apply m => ObservableT m a -> ObservableT m b -> ObservableT m b 505 | mergeMapTo = combineInner mergeMapTo_ 506 | 507 | -- | Given an accumulator function (arg1), an initial value (arg2), and 508 | -- | a source ObservableImpl (arg3), it returns an ObservableImpl that emits the current 509 | -- | accumlation whenever the source emits a value. 510 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/scanSeed.png) 511 | scan :: forall a b f. Functor f => (a -> b -> b) -> b -> ObservableT f a -> ObservableT f b 512 | scan reducer seed = mapInner (scan_ reducer seed) 513 | 514 | -- | Same as scan except that its result is encapsulated in a monad. 515 | scanM :: forall a b m f. Functor f => Monad m => (a -> b -> m b) -> b -> ObservableT f a -> ObservableT f (m b) 516 | scanM reducer seed = scan (\a mb -> mb >>= reducer a) (pure seed) 517 | 518 | -- | It's like delay, but passes only the most recent value from each burst of emissions. 519 | debounceTime :: forall a f. Functor f => Int -> ObservableT f a -> ObservableT f a 520 | debounceTime time = mapInner (debounceTime_ time) 521 | -- | Returns an Observable that emits all items emitted by the source Observable 522 | -- | that are distinct by comparison from previous items. 523 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/distinct.png) 524 | distinct :: forall a f. Functor f => ObservableT f a -> ObservableT f a 525 | distinct = mapInner distinct_ 526 | 527 | -- | Returns an Observable that emits all items emitted by the source Observable 528 | -- | that are distinct by comparison from the previous item. 529 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/distinctUntilChanged.key.png) 530 | distinctUntilChanged :: forall a f. Functor f => ObservableT f a -> ObservableT f a 531 | distinctUntilChanged = mapInner distinctUntilChanged_ 532 | 533 | -- | Emits the single value at the specified index in a sequence of emissions 534 | -- | from the source 535 | elementAt :: forall a f. Functor f => Int -> ObservableT f a -> ObservableT f a 536 | elementAt index = mapInner (elementAt_ index) 537 | 538 | -- | Filter items emitted by the source Observable by only emitting those that 539 | -- | satisfy a specified predicate. 540 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/filter.png) 541 | filter :: forall a f. Functor f => (a -> Boolean) -> ObservableT f a -> ObservableT f a 542 | filter predicate = mapInner (filter_ predicate) 543 | 544 | -- | Ignores all items emitted by the source Observable and only passes calls of complete or error. 545 | -- | ![marble diagram](http://reactivex.io/rxjs/img/ignoreElements.png) 546 | ignoreElements :: forall a f. Functor f => ObservableT f a -> ObservableT f a 547 | ignoreElements = mapInner ignoreElements_ 548 | 549 | -- | Returns an Observable that emits only the last item emitted by the source 550 | -- | Observable that that satisfies the given predicate. 551 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/last.png) 552 | last :: forall a f. Functor f => (a -> Boolean) -> ObservableT f a -> ObservableT f a 553 | last predicate = mapInner (last_ predicate) 554 | 555 | 556 | -- | It's like sampleTime, but samples whenever the notifier Observable emits something. 557 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/sample.o.png) 558 | sample :: forall a b f. Apply f => ObservableT f b -> ObservableT f a -> ObservableT f a 559 | sample = combineInner sample_ 560 | 561 | 562 | -- | Periodically looks at the source Observable and emits whichever 563 | -- | value it has most recently emitted since the previous sampling, unless the source has not emitted anything since the previous sampling. 564 | sampleTime :: forall a f. Functor f => Int -> ObservableT f a -> ObservableT f a 565 | sampleTime time = mapInner (sampleTime_ time) 566 | 567 | -- | Returns an Observable that skips n items emitted by an 568 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/skip.png) 569 | skip :: forall a f. Functor f => Int -> ObservableT f a -> ObservableT f a 570 | skip amount = mapInner (skip_ amount) 571 | 572 | -- | Returns an Observable that skips items emitted by the source Observable until a second Observable emits an item. 573 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/skipUntil.png) 574 | skipUntil :: forall a b f. Apply f => ObservableT f b -> ObservableT f a -> ObservableT f a 575 | skipUntil = combineInner skipUntil_ 576 | 577 | -- | Returns an Observable that skips all items emitted 578 | -- | by the source Observable as long as a specified condition holds true, 579 | -- | but emits all further source items as soon as the condition becomes false. 580 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/skipWhile.png) 581 | skipWhile :: forall a f. Functor f => (a -> Boolean) -> ObservableT f a -> ObservableT f a 582 | skipWhile predicate = mapInner (skipWhile_ predicate) 583 | 584 | -- | Emits only the first n values emitted by the source 585 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/take.png) 586 | take :: forall a f. Functor f => Int -> ObservableT f a -> ObservableT f a 587 | take amount = mapInner (take_ amount) 588 | 589 | -- | Lets values pass until a second Observable emits something. Then, it completes. 590 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/takeUntil.png" alt="" 591 | takeUntil :: forall a b f. Apply f => ObservableT f b -> ObservableT f a -> ObservableT f a 592 | takeUntil = combineInner takeUntil_ 593 | 594 | -- | Emits values emitted by the source Observable so long as each value satisfies 595 | -- | the given predicate, and then completes as soon as this predicate is not satisfied. 596 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/takeWhile.png) 597 | takeWhile :: forall a f. Functor f => (a -> Boolean) -> ObservableT f a -> ObservableT f a 598 | takeWhile predicate = mapInner (takeWhile_ predicate) 599 | 600 | -- | Ignores source values for duration milliseconds, 601 | -- | then emits the most recent value from the source Observable, then repeats this process. 602 | -- | ![marble diagram](http://reactivex.io/rxjs/img/auditTime.png) 603 | auditTime :: forall a f. Functor f => Int -> ObservableT f a -> ObservableT f a 604 | auditTime time = mapInner (auditTime_ time) 605 | 606 | 607 | -- | Emits a value from the source Observable, then ignores subsequent source values 608 | -- | for duration milliseconds, then repeats this process. 609 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/throttleWithTimeout.png) 610 | throttleTime :: forall a f. Functor f => Int -> ObservableT f a -> ObservableT f a 611 | throttleTime time = mapInner (throttleTime_ time) 612 | 613 | 614 | -- | Returns an Observable that emits the items in the given Foldable before 615 | -- | it begins to emit items emitted by the source Observable. 616 | startWithMany :: forall f a m. Foldable f => Functor m => f a -> ObservableT m a -> ObservableT m a 617 | startWithMany xs obs = 618 | foldr (\cur acc -> startWith cur acc) obs xs 619 | 620 | -- | Returns an Observable that emits the item given before 621 | -- | it begins to emit items emitted by the source Observable. 622 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/startWith.png) 623 | startWith :: forall a f. Functor f => a -> ObservableT f a -> ObservableT f a 624 | startWith a = mapInner (startWith_ a) 625 | 626 | -- | Combines each value from the source Observables using a project function to 627 | -- | determine the value to be emitted on the output 628 | -- | ![marble diagram](https://raw.github.com/wiki/ReactiveX/RxJava/images/rx-operators/withLatestFrom.png) 629 | withLatestFrom :: forall a b c f. Apply f => (a -> b -> c) -> ObservableT f b -> ObservableT f a -> ObservableT f c 630 | withLatestFrom selector = combineInner (withLatestFrom_ selector) 631 | 632 | 633 | -- | Concatenates two Observables together by sequentially emitting their values, one Observable after the other. 634 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/concat.png) 635 | concat :: forall a f. Apply f => ObservableT f a -> ObservableT f a -> ObservableT f a 636 | concat = combineInner concat_ 637 | 638 | -- | It's like switchMap, but maps each value to the same inner ObservableImpl. 639 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/switchMap.png) 640 | switchMapTo :: forall a b f. Apply f => ObservableT f b -> ObservableT f a -> ObservableT f b 641 | switchMapTo = combineInner switchMapTo_ 642 | 643 | -- | If the source Observable calls error, this method will resubscribe to the 644 | -- | source Observable n times rather than propagating the error call. 645 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/retry.png) 646 | retry :: forall a f. Functor f => Int -> ObservableT f a -> ObservableT f a 647 | retry amount = mapInner (retry_ amount) 648 | 649 | -- Utility Operators 650 | -- | Time shifts each item by some specified amount of milliseconds. 651 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/delay.png) 652 | delay :: forall a f. Functor f => Int -> ObservableT f a -> ObservableT f a 653 | delay ms = mapInner (delay_ ms) 654 | 655 | 656 | 657 | -- | Returns an Observable that emits the items emitted by the source Observable or a specified default item 658 | -- | if the source Observable is empty. 659 | -- | 660 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/defaultIfEmpty.c.png) 661 | -- | 662 | -- | takes a defaultValue which is the item to emit if the source Observable emits no items. 663 | -- | 664 | -- | returns an Observable that emits either the specified default item if the source Observable emits no 665 | -- | items, or the items emitted by the source Observable 666 | defaultIfEmpty :: forall a f. Functor f => a -> ObservableT f a -> ObservableT f a 667 | defaultIfEmpty default = mapInner (defaultIfEmpty_ default) 668 | 669 | 670 | -- | Determines whether all elements of an observable sequence satisfy a condition. 671 | -- | Returns an observable sequence containing a single element determining whether all 672 | -- | elements in the source sequence pass the test in the specified predicate. 673 | every :: forall a f. Functor f => (a -> Boolean) -> ObservableT f a -> ObservableT f Boolean 674 | every predicate = mapInner (every_ predicate) 675 | -- | Tests whether this `Observable` emits no elements. 676 | -- | 677 | -- | returns an Observable emitting one single Boolean, which is `true` if this `Observable` 678 | -- | emits no elements, and `false` otherwise. 679 | isEmpty :: forall a f. Functor f => ObservableT f a -> ObservableT f Boolean 680 | isEmpty = mapInner isEmpty_ 681 | 682 | -- | Returns a new Observable that multicasts (shares) the original Observable. As long a 683 | -- | there is more than 1 Subscriber, this Observable will be subscribed and emitting data. 684 | -- | When all subscribers have unsubscribed it will unsubscribe from the source Observable. 685 | -- | 686 | -- | This is an alias for `publish().refCount()` 687 | -- | 688 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/publishRefCount.png) 689 | -- | 690 | -- | returns an Observable that upon connection causes the source Observable to emit items to its Subscribers 691 | share :: forall a f. Functor f => ObservableT f a -> ObservableT f a 692 | share = mapInner share_ 693 | 694 | -- | Returns an Observable that emits only the first item emitted by the source 695 | -- | Observable that satisfies the given predicate. 696 | first :: forall a f. Functor f => (a -> Boolean) -> ObservableT f a -> ObservableT f a 697 | first predicate = mapInner (first_ predicate) 698 | 699 | -- | Counts the number of emissions on the source and emits that number when the source completes. 700 | count :: forall a f. Functor f => ObservableT f a -> ObservableT f Int 701 | count = mapInner count_ 702 | -- | Applies an accumulator function over the source Observable, and returns the accumulated 703 | -- | result when the source completes, given a seed value. 704 | reduce :: forall a b f. Functor f => (a -> b -> b) -> b -> ObservableT f a -> ObservableT f b 705 | reduce accumulator seed = mapInner (reduce_ accumulator seed) 706 | 707 | -- | Makes every `next` call run in the new Scheduler. 708 | observeOn :: forall a f. Functor f => Scheduler -> ObservableT f a -> ObservableT f a 709 | observeOn scheduler = mapInner (observeOn_ scheduler) 710 | 711 | -- | Makes subscription happen on a given Scheduler. 712 | subscribeOn :: forall a f. Functor f => Scheduler -> ObservableT f a -> ObservableT f a 713 | subscribeOn scheduler = mapInner (subscribeOn_ scheduler) 714 | 715 | -- Subscribe to an ObservableImpl, supplying only the `next` function. 716 | subscribeNext :: forall a f u. Functor f => (a -> Effect u) -> ObservableT f a -> f (Effect Subscription) 717 | subscribeNext next (ObservableT fo) = map (subscribeNext_ next) fo 718 | 719 | --foreign import subscribeNext_' :: forall a e u. (a -> Effect u) -> ObservableImpl a -> Effect Subscription 720 | 721 | create' :: forall a u. (Subscriber a -> Effect u) -> ObservableT (Effect) a 722 | create' fn = ObservableT (create_ fn) 723 | 724 | --foreign import bind' :: forall m a b. Monad m => m a -> (a -> m b) -> m b 725 | --foreign import join' :: forall m a. Monad m => m (m a) -> m a 726 | 727 | -- create -> Effect (Observable a) 728 | -- subscribeToOuter -> m (Effect Subscription) 729 | -- inner :: a 730 | 731 | 732 | {- 733 | outer :: m (ObservableImpl (m (ObservableImpl a))) 734 | -} 735 | join_ :: forall m a. Monad m => ObservableT m (ObservableT m a) -> ObservableT m a 736 | join_ outer = create(\observer -> 737 | pure (outer # subscribeNext (\monadOfInner -> 738 | pure (monadOfInner # subscribeNext(\value -> 739 | observer.next value 740 | ) # map unsafePerformEffect) 741 | ) # map unsafePerformEffect) 742 | ) # runObservableT # unsafePerformEffect # pure # ObservableT 743 | 744 | 745 | -- | Subscribing to an ObservableImpl is like calling a function, providing 746 | -- | `next`, `error` and `completed` effects to which the data will be delivered. 747 | subscribe :: forall a f. Functor f => Subscriber a -> ObservableT f a -> f (Effect Subscription) 748 | subscribe subscriber (ObservableT fo) = map (subscribe_ subscriber) fo 749 | 750 | -- | Returns an ObservableImpl that reverses the effect of `materialize` by 751 | -- | `Notification` objects emitted by the source ObservableImpl into the items 752 | -- | or notifications they represent. 753 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/dematerialize.png) 754 | dematerialize :: forall a f. Functor f => ObservableT f (Notification a) -> ObservableT f a 755 | dematerialize = mapInner (\o -> dematerialize_ o) 756 | 757 | -- | Turns all of the notifications from a source ObservableImpl into onNext emissions, 758 | -- | and marks them with their original notification types within `Notification` objects. 759 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/materialize.png) 760 | materialize :: forall a f. Functor f => ObservableT f a -> ObservableT f (Notification a) 761 | materialize = mapInner (\o -> runFn4 materializeImpl o OnNext OnError OnComplete) 762 | 763 | 764 | -- | Returns an ObservableImpl that emits a single item, a list composed of all the items emitted by the source ObservableImpl. 765 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/toList.png) 766 | toArray :: forall a f. Functor f => ObservableT f a -> ObservableT f (Array a) 767 | toArray = mapInner toArray_ 768 | 769 | --Observable only 770 | 771 | unwrapInnerFn :: forall a b c. Comonad c => (a -> ObservableT c b) -> a -> ObservableImpl b 772 | unwrapInnerFn fn a = unwrapId (fn a) 773 | 774 | unwrapId :: forall a c. Comonad c => ObservableT c a -> ObservableImpl a 775 | unwrapId = runObservableT >>> extract 776 | 777 | unwrapEff :: forall a. Observable (Effect a) -> ObservableT (Effect) a 778 | unwrapEff = unwrapId >>> unwrap_ >>> ObservableT 779 | 780 | 781 | -- | Collects values from the source ObservableImpl (arg1) as an array. Starts collecting only when 782 | -- | the opening (arg2) ObservableImpl emits, and calls the closingSelector function (arg3) to get an ObservableImpl 783 | -- | that decides when to close the buffer. Another buffer opens when the 784 | -- | opening ObservableImpl emits its next value. 785 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/buffer2.png) 786 | bufferToggle 787 | :: forall a b c. Observable a 788 | -> Observable b 789 | -> (b -> Observable c) 790 | -> Observable (Array a) 791 | bufferToggle as bs f = liftT (runFn3 bufferToggleImpl_ (unwrapId as) (unwrapId bs) (unwrapInnerFn f)) 792 | 793 | 794 | -- | It's like auditTime, but the silencing duration is determined by a second ObservableImpl. 795 | -- | ![marble diagram](http://reactivex.io/rxjs/img/audit.png) 796 | audit :: forall a b. (a -> Observable b) -> Observable a -> Observable a 797 | audit fn as = liftT $ audit_ (unwrapInnerFn fn) (unwrapId as) 798 | 799 | 800 | -- | It's like debounceTime, but the time span of emission silence is determined 801 | -- | by a second ObservableImpl. Allows for a variable debounce rate. 802 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/debounce.f.png) 803 | debounce :: forall a. (a -> Observable Int) -> Observable a -> Observable a 804 | debounce fn as = liftT $ debounce_ (unwrapInnerFn fn) (unwrapId as) 805 | 806 | -- | Collects values from the past as an array. When it starts collecting values, 807 | -- | it calls a function that returns an ObservableImpl that emits to close the 808 | -- | buffer and restart collecting. 809 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/buffer1.png) 810 | bufferWhen :: forall a b. (a -> Observable b) -> Observable a -> Observable (Array a) 811 | bufferWhen fn as = liftT $ bufferWhen_ (unwrapInnerFn fn) (unwrapId as) 812 | 813 | 814 | -- | Equivalent to mergeMap (a.k.a, `>>=`) EXCEPT that, unlike mergeMap, 815 | -- | the next bind will not run until the ObservableImpl generated by the projection function (arg2) 816 | -- | completes. That is, composition is sequential, not concurrent. 817 | -- | Warning: if source values arrive endlessly and faster than their corresponding 818 | -- | inner ObservableImpls can complete, it will result in memory issues as inner 819 | -- | ObservableImpls amass in an unbounded buffer waiting for their turn to be subscribed to. 820 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/concatMap.png) 821 | concatMap :: forall a b. (a -> Observable b) -> Observable a -> Observable b 822 | concatMap fn as = liftT $ concatMap_ (unwrapInnerFn fn) (unwrapId as) 823 | 824 | 825 | 826 | -- | It's Like concatMap (a.k.a, `>>=`) EXCEPT that it ignores every new projected 827 | -- | ObservableImpl if the previous projected ObservableImpl has not yet completed. 828 | -- | ![marble diagram](http://reactivex.io/rxjs/img/exhaustMap.png) 829 | exhaustMap :: forall a b. (a -> Observable b) -> Observable a -> Observable b 830 | exhaustMap fn as = liftT $ exhaustMap_ (unwrapInnerFn fn) (unwrapId as) 831 | 832 | 833 | -- | It's similar to mergeMap, but applies the projection function to every source 834 | -- | value as well as every output value. It's recursive. 835 | expand :: forall a. (a -> Observable a) -> Observable a -> Observable a 836 | expand fn as = liftT $ expand_ (unwrapInnerFn fn) (unwrapId as) 837 | 838 | -- | Groups the items emitted by an ObservableImpl (arg2) according to the value 839 | -- | returned by the grouping function (arg1). Each group becomes its own 840 | -- | ObservableImpl. 841 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/groupBy.png) 842 | groupBy :: forall a b. (a -> b) -> Observable a -> Observable (Observable a) 843 | groupBy fn as = map liftT (liftT $ groupBy_ fn (unwrapId as)) 844 | 845 | 846 | -- | Projects each source value to an ObservableImpl which is merged in the output 847 | -- | ObservableImpl, emitting values only from the most recently projected ObservableImpl. 848 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/switchMap.png) 849 | switchMap :: forall a b. (a -> Observable b) -> Observable a -> Observable b 850 | switchMap f as = liftT $ switchMap_ (unwrapInnerFn f) (unwrapId as) 851 | 852 | -- | Delays the emission of items from the source ObservableImpl by a given time 853 | -- | span determined by the emissions of another ObservableImpl. 854 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/delay.o.png) 855 | delayWhen :: forall a b. (a -> Observable b) -> Observable a -> Observable a 856 | delayWhen f as = liftT $ delayWhen_ (unwrapInnerFn f) (unwrapId as) 857 | 858 | -- | Converts a higher-order ObservableImpl into a first-order ObservableImpl by concatenating the inner ObservableImpls in order. 859 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/concat.png) 860 | concatAll :: forall a. Observable (Observable a) -> Observable a 861 | concatAll ho = liftT $ concatAll_ (unwrapId (map unwrapId ho)) 862 | 863 | -- | Converts a higher-order ObservableImpl into a first-order ObservableImpl 864 | -- | which concurrently delivers all values that are emitted on the inner ObservableImpls. 865 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/mergeAll.png) 866 | mergeAll :: forall a. Observable (Observable a) -> Observable a 867 | mergeAll ho = liftT $ mergeAll_ (unwrapId (map unwrapId ho)) 868 | 869 | -- | Returns an ObservableImpl that mirrors the first source ObservableImpl to emit an 870 | -- | item from the array of ObservableImpls. 871 | race :: forall a. Array (Observable a) -> Observable a 872 | race arr = liftT $ race_ (map unwrapId arr) 873 | 874 | -- | Flattens an Observable-of-Observable by dropping the next inner Observables 875 | -- | while the current inner is still executing. 876 | -- | ![marble diagram](http://reactivex.io/rxjs/img/exhaust.png) 877 | exhaust :: forall a. Observable (Observable a) -> Observable a 878 | exhaust ho = liftT $ exhaust_ (unwrapId (map unwrapId ho)) 879 | 880 | -- | It's like buffer, but emits a nested ObservableImpl instead of an array. 881 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/window8.png) 882 | window :: forall a b. Observable b -> Observable a -> Observable (Observable a) 883 | window bs as = map liftT (liftT $ window_ (unwrapId bs) (unwrapId as)) 884 | 885 | 886 | -- | It's like bufferCount, but emits a nested ObservableImpl instead of an array. 887 | windowCount :: forall a. Int -> Int -> Observable a -> Observable (Observable a) 888 | windowCount size offset as = map liftT (liftT $ windowCount_ size offset (unwrapId as)) 889 | 890 | -- | It's like bufferTime, but emits a nested ObservableImpl instead of an array, 891 | -- | and it doesn't take a maximum size parameter. arg1 is how long to 892 | -- | buffer items into a new ObservableImpl, arg2 is the when the next buffer should begin, 893 | -- | and arg3 is the source ObservableImpl. 894 | windowTime :: forall a. Int -> Int -> Observable a -> Observable (Observable a) 895 | windowTime time opens as = map liftT (liftT $ windowTime_ time opens (unwrapId as)) 896 | 897 | 898 | -- | It's like throttleTime, but the silencing duration is determined by a second ObservableImpl. 899 | -- | ![marble diagram](http://reactivex.io/rxjs/img/throttle.png) 900 | throttle :: forall a b. (a -> Observable b) -> Observable a -> Observable a 901 | throttle f as = liftT $ throttle_ (unwrapInnerFn f) (unwrapId as) 902 | 903 | -- | Waits for each ObservableImpl to emit a value. Once this occurs, all values 904 | -- | with the corresponding index will be emitted. This will continue until at 905 | -- | least one inner ObservableImpl completes. 906 | -- | ![marble diagram](https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/zip.i.png) 907 | zip :: forall a. Array (Observable a) -> Observable (Array a) 908 | zip arr = liftT $ zip_ (map unwrapId arr) 909 | 910 | -- Error Handling Operators 911 | -- | ![marble diagram](http://reactivex.io/documentation/operators/images/catch.js.png) 912 | catch :: forall a. Observable a -> (Error -> Observable a) -> Observable a 913 | catch as f = liftT $ catch_ (unwrapId as) (unwrapInnerFn f) 914 | --------------------------------------------------------------------------------