Skip to content

Instantly share code, notes, and snippets.

@cbueno360
Last active April 21, 2023 14:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cbueno360/bb1163cb144b89ccefb77984c2faa954 to your computer and use it in GitHub Desktop.
Save cbueno360/bb1163cb144b89ccefb77984c2faa954 to your computer and use it in GitHub Desktop.
var counterAgent = new CounterAgent();
counterAgent.Post(new CounterMessage { Action = CounterMessage.ActionType.Increment, Value = 5 });
counterAgent.Post(new CounterMessage { Action = CounterMessage.ActionType.Decrement, Value = 2 });
counterAgent.Post(new CounterMessage { Action = CounterMessage.ActionType.Reset });
int sum = ApplyFunction((x, y) => x + y, 5, 3);
int product = ApplyFunction((x, y) => x * y, 5, 3);
public class ChatMessage
{
public enum ActionType
{
SendMessage,
GetAllMessages
}
public ActionType Action { get; set; }
public string Message { get; set; }
public FSharpAsync<List<string>> ReplyChannel { get; set; }
}
public class ChattyAgent : Agent<List<string>, ChatMessage>
{
public ChattyAgent() : base(new List<string>(), (state, message) =>
{
switch (message.Action)
{
case ChatMessage.ActionType.SendMessage:
state.Add(message.Message);
return state;
case ChatMessage.ActionType.GetAllMessages:
FSharpAsync.StartAsTask(message.ReplyChannel).ContinueWith(t => t.Result(state));
return state;
default:
throw new ArgumentOutOfRangeException("Oh no! The chatty agent has no idea what's going on!");
}
})
{ }
}
type AccountMessage =
| Deposit of float
| Withdraw of float
| GetBalance of AsyncReplyChannel<float>
type BankMessage =
| OpenAccount of AsyncReplyChannel<MailboxProcessor<AccountMessage>>
| CloseAccount of MailboxProcessor<AccountMessage>
let accountAgent (initialBalance: float) =
MailboxProcessor.Start(fun inbox ->
let rec loop balance =
async {
let! message = inbox.Receive()
match message with
| Deposit amount -> return! loop (balance + amount)
| Withdraw amount ->
if balance >= amount then
return! loop (balance - amount)
else
return! loop balance
| GetBalance replyChannel ->
replyChannel.Reply balance
return! loop balance
}
loop initialBalance
)
let bankAgent =
MailboxProcessor.Start(fun inbox ->
let rec loop accounts =
async {
let! message = inbox.Receive()
match message with
| OpenAccount replyChannel ->
let newAccount = accountAgent 0.0
replyChannel.Reply newAccount
return! loop (newAccount :: accounts)
| CloseAccount account ->
let updatedAccounts = accounts |> List.filter (fun acc -> acc <> account)
return! loop updatedAccounts
}
loop []
)
let createAccountAsync = bankAgent.PostAndAsyncReply(OpenAccount)
let newAccount = Async.RunSynchronously createAccountAsync
newAccount.Post(Deposit 100.0)
newAccount.Post(Withdraw 50.0)
let getBalanceAsync = newAccount.PostAndAsyncReply(GetBalance)
Async.RunSynchronously getBalanceAsync |> printfn "Account balance: %f"
// C# example: Creating a simple class
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName()
{
return $"{FirstName} {LastName}";
}
}
// Using the Person class
Person person = new Person { FirstName = "John", LastName = "Doe" };
Console.WriteLine(person.FullName());
public int Factorial(int n) => n == 0 ? 1 : n * Factorial(n - 1);
type Shape =
| Circle of radius: float
| Rectangle of width: float * height: float
let area shape =
match shape with
| Circle radius -> Math.PI * radius * radius
| Rectangle (width, height) -> width * height
let circle = Circle 5.0
let rectangle = Rectangle (3.0, 4.0)
printfn "Circle area: %f" (area circle)
printfn "Rectangle area: %f" (area rectangle)
// F# example: Creating a simple record type
type Person = { FirstName: string; LastName: string }
// Function to return the full name
let fullName person = person.FirstName + " " + person.LastName
// Using the Person record type
let person = { FirstName = "John"; LastName = "Doe" }
printfn "%s" (fullName person)
let numbers = [1; 2; 3; 4; 5]
let double x = x * 2
let isEven x = x % 2 = 0
let doubledNumbers = List.map double numbers
let evenNumbers = List.filter isEven numbers
printfn "Doubled numbers: %A" doubledNumbers
printfn "Even numbers: %A" evenNumbers
public int ApplyFunction(Func<int, int, int> function, int x, int y)
{
return function(x, y);
}
public class ImmutablePerson
{
public string FirstName { get; init; }
public string LastName { get; init; }
public ImmutablePerson(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
}
public int Add(int x, int y)
{
return x + y;
}
type CounterMessage =
| Increment
| Decrement
| GetState of AsyncReplyChannel<int>
let counterAgent =
MailboxProcessor.Start(fun inbox ->
let rec loop count =
async {
let! message = inbox.Receive()
match message with
| Increment -> return! loop (count + 1)
| Decrement -> return! loop (count - 1)
| GetState replyChannel ->
replyChannel.Reply count
return! loop count
}
loop 0
)
counterAgent.Post(Increment)
counterAgent.Post(Increment)
counterAgent.Post(Decrement)
let getCountAsync = counterAgent.PostAndAsyncReply(GetState)
Async.RunSynchronously getCountAsync |> printf "nCurrent count: %d\n"
using System;
using FSharp.Core;
using FSharp.Control;
public class Agent<TState, TMessage>
{
private readonly MailboxProcessor<TMessage> _mailbox;
public Agent(TState initialState, Func<TState, TMessage, TState> processMessage)
{
_mailbox = new MailboxProcessor<TMessage>(async inbox =>
{
var state = initialState;
while (true)
{
var message = await inbox.Receive();
state = processMessage(state, message);
}
});
}
public void Post(TMessage message)
{
_mailbox.Post(message);
}
}
open System
type CounterMessage =
| Increment
| Decrement
let counterAgent =
MailboxProcessor.Start(fun inbox ->
let rec loop count =
async {
let! message = inbox.Receive()
match message with
| Increment -> return! loop (count + 1)
| Decrement -> return! loop (count - 1)
}
loop 0
)
counterAgent.Post(Increment)
counterAgent.Post(Increment)
counterAgent.Post(Decrement)
public class CounterMessage
{
public enum ActionType
{
Increment,
Decrement,
Reset
}
public ActionType Action { get; set; }
public int Value { get; set; }
}
public class CounterAgent : Agent<int, CounterMessage>
{
public CounterAgent() : base(0, (state, message) =>
{
switch (message.Action)
{
case CounterMessage.ActionType.Increment:
return state + message.Value;
case CounterMessage.ActionType.Decrement:
return state - message.Value;
case CounterMessage.ActionType.Reset:
return 0;
default:
throw new ArgumentOutOfRangeException("Oops! The counter agent got confused!");
}
})
{ }
}
var chattyAgent = new ChattyAgent();
chattyAgent.Post(new ChatMessage { Action = ChatMessage.ActionType.SendMessage, Message = "Hello, world!" });
chattyAgent.Post(new ChatMessage { Action = ChatMessage.ActionType.SendMessage, Message = "Agents are cool!" });
var replyChannel = FSharpAsync.Create<List<string>>(asyncResult => { });
chattyAgent.Post(new ChatMessage { Action = ChatMessage.ActionType.GetAllMessages, ReplyChannel = replyChannel });
var messages = FSharpAsync.RunSynchronously(replyChannel);
foreach (var message in messages)
{
Console.WriteLine(message);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment