2016-06-21 4 views
5

F #에서 지원자를하는 방법?

let y() = Success (fun x -> x + 1) <*> (Success 3) 

나는 다음과 같은 오류를 얻을 다음과 같은 유형 및 멤버 함수

type Result<'TSuccess, 'TError> = 
    | Success of 'TSuccess 
    | Error of 'TError list 
    with 
    member this.apply fn = 
     match (fn, this) with 
     | Success(f), Success(x) -> Success(f x) 
     | Error(e), Success(_) -> Error(e) 
     | Success(_), Error(e) -> Error(e) 
     | Error(e1), Error(e2) -> Error(List.concat [e1;e2]) 

다음과 같은 인라인 기능

let inline (<*>) (f: ^A) (t:^A) = 
    let apply' = (^A : (member apply : ^A -> ^A) (t, f)) 
    apply' 

그리고이 호출이 사이트를 감안할 때

let y() = Success (fun x -> x + 1) <*> (Success 3);; 
-----------^^^^^^^^^^^^^^^^^^^^^^^^ 
/Users/robkuz/stdin(473,12): error FS0001: Type constraint mismatch. 
The type 
    Result<'a,'c> 
is not compatible with type 
    Result<('a -> 'b),'c> 
The resulting type would be infinite when unifying ''a' and ''a -> 'b' 
,

이 모든 것은 Haskells 실용적을 모방하려는 시도이며, 서명은

(<*>) :: forall f a b. Apply f => f (a -> b) -> f a -> f b 

해야하지만 F 번호

이 일어날 수 있도록하는 방법에 어떤 아이디어에서 그것을 표현하는 방법이 없습니다 AFAIK 해달라고?

+0

@Thomas가 제공하는 솔루션은 귀하의 경우에는 괜찮지만 기본 유형 (목록, 배열, 옵션)에서는 작동하지 않으며 모나드와 자동으로 작동하지 않습니다. [더 완벽한 해결책] (https://github.com/gmpl/FsControl/blob/master/FsControl.Core/Functor.fs#L133)이 있습니다. – Gustavo

답변

7

일반적으로 F #에서 하스켈 패턴을 에뮬레이트하려고하지 않는 것이 좋습니다. 하스켈에서는 모나드와 응용 프로그램이 자주 사용되기 때문에 많은 코드가 매우 일반적으로 작성되었습니다.

F #에서는 모나드 또는 응용 프로그램에 대해 다형성 코드를 작성할 필요가 없으므로 더 전문화 된 코드를 작성하는 것이 더 좋으며 실제로 어떤 일이 일어나는지 쉽게 알 수 있습니다. 그래서, 나는 F #에서 실제 "applicative"이상으로 작동하는 <*> 연산자를 쓰고 싶지 않을 것이라고 생각합니다.

당신의 코드 문제는 <*> 연산자가 인자와 결과 모두에 대해 동일한 ^A 유형 매개 변수를 사용한다는 것입니다 (호출시 다른 유형 임) - 세 개의 개별 유형 매개 변수를 사용하면 잘 작동합니다. :

let inline (<*>) (f: ^B) (t:^A) : ^C = 
    let apply' = (^A : (member apply : ^B -> ^C) (t, f)) 
    apply'