수색…


공통 연산자를 사용하여 값과 함수를 작성하는 방법

객체 지향 프로그래밍에서 일반적인 작업은 객체 (값)를 작성하는 것입니다. 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# 전진 배관은 역 배관보다 선호됩니다.

  1. 타입 유추 (일반적으로)는 왼쪽에서 오른쪽으로 흐르므로 값과 함수가 왼쪽에서 오른쪽으로도 자연스럽게 나옵니다.
  2. 왜냐하면 <| << 는 오른쪽 연관성을 가져야하지만 F# 에서는 왼쪽으로 결합되어 삽입 ()
  3. 정방향 및 역방향 혼합 배관은 같은 우선 순위를 가지기 때문에 일반적으로 작동하지 않습니다.

모나드 조성

함수 프로그래밍에서 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# 지원은 간단하면서도 유연합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow