Skip to content

Instantly share code, notes, and snippets.

@bleis-tift
Created November 30, 2016 01:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bleis-tift/c8419630f982aa5ff71c8f0af659778a to your computer and use it in GitHub Desktop.
Save bleis-tift/c8419630f982aa5ff71c8f0af659778a to your computer and use it in GitHub Desktop.
//================================================================================
// 共通
//================================================================================
type EmailAddress =
{ EAValue: string }
type SurfaceAddress =
{ SAValue: string }
type Customer =
{ EmailAddress: EmailAddress
SurfaceAddress: SurfaceAddress }
type ShoppingCart<'TItem> =
{ Items: 'TItem list }
//================================================================================
// F# way (DU + match(function) expr)
//================================================================================
type Item =
| FDownloadableItem
| FSurfaceItem
module FunctionalShipping =
let ship customer = function
| FDownloadableItem -> printfn "%sにダウンロードURL付きメールを送信" customer.EmailAddress.EAValue
| FSurfaceItem -> printfn "%sに配送" customer.SurfaceAddress.SAValue
module FunctionalShoppingCart =
let empty : ShoppingCart<Item> = { Items = [] }
let add (item: Item) cart = { cart with Items = item::cart.Items }
let shipAll customer cart =
cart.Items
|> List.iter (FunctionalShipping.ship customer)
//================================================================================
// Objective way(double dispatch(polymorphism))
//================================================================================
type IItem =
abstract Ship: shipper:ObjectiveShipping * customer:Customer -> unit
and ObjectiveShipping () =
member __.Ship(item: IItem, emailAddress: EmailAddress) =
printfn "%sにダウンロードURL付きメールを送信" emailAddress.EAValue
member __.Ship(item: IItem, surfaceAddress: SurfaceAddress) =
printfn "%sに配送" surfaceAddress.SAValue
type ODownloadableItem () =
interface IItem with
member this.Ship(shipper, customer) =
shipper.Ship(this, customer.EmailAddress)
type OSurfaceItem () =
interface IItem with
member this.Ship(shipper, customer) =
shipper.Ship(this, customer.SurfaceAddress)
module ObjectiveShoppingCart =
let empty : ShoppingCart<IItem> = { Items = [] }
let add (item: IItem) cart = { cart with Items = item::cart.Items }
let shipAll customer (cart: ShoppingCart<IItem>) =
let shipper = ObjectiveShipping ()
cart.Items
|> List.iter (fun item -> item.Ship(shipper, customer))
//================================================================================
// usage
//================================================================================
let customer =
{ EmailAddress = { EAValue = "admin@example.com" }
SurfaceAddress = { SAValue = "どこか" } }
// F# way
let fcart =
FunctionalShoppingCart.empty
|> FunctionalShoppingCart.add FDownloadableItem
|> FunctionalShoppingCart.add FSurfaceItem
fcart |> FunctionalShoppingCart.shipAll customer
// Objective way
let ocart =
ObjectiveShoppingCart.empty
|> ObjectiveShoppingCart.add (ODownloadableItem())
|> ObjectiveShoppingCart.add (OSurfaceItem())
ocart |> ObjectiveShoppingCart.shipAll customer
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment