수색…
공통 연산자를 사용하여 값과 함수를 작성하는 방법
객체 지향 프로그래밍에서 일반적인 작업은 객체 (값)를 작성하는 것입니다. Functional Programming에서는 기능뿐만 아니라 값을 구성하는 것이 일반적인 작업입니다.
우리는 +
, -
, *
, /
등과 같은 연산자를 사용하여 다른 프로그래밍 언어 경험을 통해 가치를 구성하는 데 사용됩니다.
가치 구성
let x = 1 + 2 + 3 * 2
함수형 프로그래밍은 값뿐만 아니라 함수를 구성하기 때문에 >>
, <<
, |>
및 <|
와 같은 함수 작성을위한 일반적인 연산자가 있습니다. .
기능 구성
// val f : int -> int
let f v = v + 1
// val g : int -> int
let g v = v * 2
// Different ways to compose f and g
// val h : int -> int
let h1 v = g (f v)
let h2 v = v |> f |> g // Forward piping of 'v'
let h3 v = g <| (f <| v) // Reverse piping of 'v' (because <| has left associcativity we need ())
let h4 = f >> g // Forward functional composition
let h5 = g << f // Reverse functional composition (closer to math notation of 'g o f')
F#
전진 배관은 역 배관보다 선호됩니다.
- 타입 유추 (일반적으로)는 왼쪽에서 오른쪽으로 흐르므로 값과 함수가 왼쪽에서 오른쪽으로도 자연스럽게 나옵니다.
- 왜냐하면
<|
<<
는 오른쪽 연관성을 가져야하지만F#
에서는 왼쪽으로 결합되어 삽입 () - 정방향 및 역방향 혼합 배관은 같은 우선 순위를 가지기 때문에 일반적으로 작동하지 않습니다.
모나드 조성
함수 프로그래밍에서 Monads ( Option<'T>
또는 List<'T>
)가 일반적으로 사용되기 때문에 >>=
, >=>
, <|>
, <*>
.
let (>>=) t uf = Option.bind uf t
let (>=>) tf uf = fun v -> tf v >>= uf
// val oinc : int -> int option
let oinc v = Some (v + 1) // Increment v
// val ofloat : int -> float option
let ofloat v = Some (float v) // Map v to float
// Different ways to compose functions working with Option Monad
// val m : int option -> float option
let m1 v = Option.bind (fun v -> Some (float (v + 1))) v
let m2 v = v |> Option.bind oinc |> Option.bind ofloat
let m3 v = v >>= oinc >>= ofloat
let m4 = oinc >=> ofloat
// Other common operators are <|> (orElse) and <*> (andAlso)
// If 't' has Some value then return t otherwise return u
let (<|>) t u =
match t with
| Some _ -> t
| None -> u
// If 't' and 'u' has Some values then return Some (tv*uv) otherwise return None
let (<*>) t u =
match t, u with
| Some tv, Some tu -> Some (tv, tu)
| _ -> None
// val pickOne : 'a option -> 'a option -> 'a option
let pickOne t u v = t <|> u <|> v
// val combine : 'a option -> 'b option -> 'c option -> (('a*'b)*'c) option
let combine t u v = t <*> u <*> v
결론
새로운 기능 프로그래머에게 연산자를 사용한 함수 구성은 불투명하고 모호하게 보일 수 있지만 이러한 연산자의 의미는 값에 대해 작업하는 연산자만큼 일반적으로 알려져 있지 않기 때문입니다. 그러나 |>
, >>
, >>=
및 >=>
사용하는 일부 교육에서는 +
, -
, *
및 /
를 사용하는 것처럼 자연스러워집니다.
F #에서 Latebinding을 사용합니까? 운영자
F#
과 같은 정적 유형 언어에서는 컴파일 할 때 잘 알려진 유형을 사용합니다. 유형 공급자를 사용하여 유형이 안전한 방식으로 외부 데이터 소스를 사용합니다.
그러나 때때로 런타임에 바인딩 ( C#
dynamic
을 사용해야 할 필요가 있습니다. 예를 들어 잘 정의 된 스키마가없는 JSON
문서로 작업 할 때.
후기 바인딩을 사용하여 작업을 단순화하기 위해 F#
은 동적 조회 연산자를 지원 ?
및 ?<-
.
예:
// (?) allows us to lookup values in a map like this: map?MyKey
let inline (?) m k = Map.tryFind k m
// (?<-) allows us to update values in a map like this: map?MyKey <- 123
let inline (?<-) m k v = Map.add k v m
let getAndUpdate (map : Map<string, int>) : int option*Map<string, int> =
let i = map?Hello // Equivalent to map |> Map.tryFind "Hello"
let m = map?Hello <- 3 // Equivalent to map |> Map.add "Hello" 3
i, m
후기 바인딩에 대한 F#
지원은 간단하면서도 유연합니다.