Skip to content

Instantly share code, notes, and snippets.

@MangelMaxime
Created August 12, 2016 09:00
Show Gist options
  • Save MangelMaxime/dae6452fbc2604280511d6d5a60d5161 to your computer and use it in GitHub Desktop.
Save MangelMaxime/dae6452fbc2604280511d6d5a60d5161 to your computer and use it in GitHub Desktop.
Used to ask a question. How to use a producer with parameters.
module Notification =
type NotificationType =
| Success
| Warning
| Danger
type Notification =
{ Id: int
Message: string
Type: NotificationType }
type Model =
{ NextId: int
Notifications: Notification list }
type Action =
| AddNotification of string
| RemoveNotification of int
let update (model: Model) action =
let model', action' =
match action with
| AddNotification msg ->
let nextId = model.NextId + 1
{ model with
NextId = nextId
Notifications =
{ Id = nextId
Message = msg
Type = Success } :: model.Notifications }, []
// Nothing here
| RemoveNotification id ->
let notifications =
model.Notifications |> List.filter(fun x -> x.Id <> id)
{ model with Notifications = notifications }, []
model', action'
let viewNotification notif =
let class' =
match notif.Type with
| Success -> Class "notification is-success"
| Danger -> Class "notification is-danger"
| Warning -> Class "notification is-warning"
div
[ class' ]
[
button
[ Class "delete" ]
[]
text notif.Message
]
let view model =
div
[]
(model.Notifications |> List.map (fun x -> viewNotification x))
let mutable scheduler = JsInterop.createEmpty<MailboxProcessor<Action>>
let addNotificationProducer h =
scheduler <- MailboxProcessor.Start(fun inbox ->
let rec loop () =
async {
let! message = inbox.Receive()
match message with
| AddNotification str ->
h (AddNotification str)
return! loop()
| _ -> return! loop()
}
loop()
)
let start () =
createApp { NextId = 0; Notifications = [] } view update
|> withStartNodeSelector "#notifications-area"
|> withProducer addNotificationProducer
|> start renderer
|> ignore
// Usage
Notification.start()
Notification.scheduler.Post(Notification.AddNotification "coucou")
Notification.scheduler.Post(Notification.AddNotification "coucou")
@mastoj
Copy link

mastoj commented Aug 12, 2016

You could try something like this to get rid of the mutable variable:

module Notification =

  type NotificationType =
    | Success
    | Warning
    | Danger

  type Notification =
    { Id: int
      Message: string
      Type: NotificationType }

  type Model =
    { NextId: int
      Notifications: Notification list }

  type Action =
    | AddNotification of string
    | RemoveNotification of int

  type ProducerMsg = 
    | Message of Action
    | AddHandler of (Action -> unit)

  type ProducerState = (Action -> unit) list
  let notificationAgent() = 
    MailboxProcessor.Start(fun inbox ->
        let rec loop state =
            async {
            let! message = inbox.Receive()
            match message with
            | Message (AddNotification str) ->
                state |> List.iter (fun s -> s (AddNotification str))
                return! loop state
            | AddHandler h -> return! loop (h::state)
            | _ -> return! loop state
            }
        loop [])

  // Usage
//Notification.start()
let notificationAgent = Notification.notificationAgent() //.Post(Notification.AddNotification "coucou")
let addHandler = (fun h -> notificationAgent.Post(Notification.AddHandler h))
addHandler (printfn "This is what you get: %A")
notificationAgent.Post(Notification.Message (Notification.AddNotification "Yolo"))

The code above should make it possible to write something like:

 |> withProducer (fun h -> notificationAgent.Post(Notification.AddHandler h))

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