문제

추가 검증 기능을 전달하는 숫자 만 일치하는 패턴을 강화하고 싶습니다.

let (|IsValid|_|) n = ...

let (|Nil|One|Two|) (l : int list) =
    match l with 
    | a :: b :: t -> Two(a + b)
    | a :: t      -> One(a)
    | _           -> Nil

'하나'사례는 쉽습니다.

    | IsValid(a) :: t -> One(a)

'두'사건은 나에게 분명하지 않습니다. 숫자의 합을 검증해야합니다. 위장을 사용하지 않고이 작업을 수행 할 수 있습니까?

...

편집 : 나는 다음과 같은 위의 가드 (bool-returning isvalid 함수)를 사용할 수 있습니다.

    | a :: b :: t when isValid a + b -> Two(a + b)

이것은 단지 패턴과 일치하는 것보다 우아합니다. 더 나쁜 것은 A + B가 두 번 적용됩니다.

또한 이것은 실제 코드의 단순화 된 버전입니다 (예 : 다른 길이의 목록과 단순히 일치하지 않으려 고하지 않습니다) - 질문은 이중 단점 패턴에 대한 중첩 일치에 관한 것입니다.

도움이 되었습니까?

해결책

내 해결책 : 부모 패턴에 사용되도록 설계된 반환 값이있는 "헬퍼"인식자를 추가하십시오.

let (|MatchTwo|_|) = function
    | a :: b :: t -> Some(a + b :: t)
    | _ -> None

그렇게 사용하십시오.

let (|Nil|One|Two|) (l : int list) =
    match l with 
    | MatchTwo(IsValid(a) :: t) -> Two(a)
    |          IsValid(a) :: t  -> One(a)
    | _                         -> Nil

다른 팁

할 때 :

| a :: b :: t -> ... 

목록에서 두 가지 요소와 반드시 일치하는 것은 아닙니다. 사용하는 것이 좋습니다 [] 대신에 t 정확히 두 가지 요소를 일치시키기 위해t 더 많은 요소 목록이 될 수 있습니다.

 | a :: b :: [] -> Two (a+b)

이렇게하면 두 가지와 두 개의 요소 만 무료로 확인하고 있습니다. 기능이 0, 1 또는 2 개의 요소 목록 만 수락 할 것으로 기대하더라도이 작업을 수행하는 것이 좋습니다. 그래서,

편집하다:

let (|MatchTwo|_|) = function
    | a :: b :: t -> Some(a + b :: t)
    | _ -> None
let (|Nil|One|Two|) (l : int list) = match l with 
    | MatchTwo(IsValid(a) :: t) -> Two(a)
    | IsValid(a) :: t  -> One(a)
    | _ -> Nil

예, 사용합니다 when. 이것은 엉망입니다. 패턴 일치는 단지 매치 내에서 함수를 적용하는 것이 실제로 의미가 없습니다. 그러나 앞에서 언급 한 내용을 고려하십시오. 예제에 따라 :

match l with
| a :: b :: t when isValid (a+b) -> Two (a+b)
| a :: t when isValid (a) -> One a
| _ -> Nil

두 번째 패턴은 첫 번째 패턴에서 isvalid가 거짓 인 경우 하나의 길이 목록과 일치합니다. 하나의 요소와 일치한다는 의미라면 가능한 한 패턴을 구체적으로 구체적으로하십시오.

A와 B를 결합하는 데 사용하는 작업 (이 경우 +)이 계산적으로 비싸면 when isvalid를 테스트하고 변형 유형을 반환하기 전에 LET 문을 사용하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top