문제
추가 검증 기능을 전달하는 숫자 만 일치하는 패턴을 강화하고 싶습니다.
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 문을 사용하십시오.