좋아, 기본적으로 바인드 연산자를 옵션 유형에 추가하려고하고 있는데, 시도한 모든 항목에 내가 수행하지 못하게하는 몇 가지 확실하지 않은 경고가있는 것으로 보입니다. .NET 유형 시스템의 한계와 관련이 있으며 아마도 사용자 코드에 typeclasses를 구현할 수없는 것과 같은 이유 일 것입니다.유형 확장자에서 연산자 오버로딩
어쨌든, 나는 두 가지 시도를했습니다.
첫째, 난 그냥 다음
let (>>=) m f = ???
내가 m
의 유형에 따라 다른 일을 할 것인지 실현했습니다. F #은 함수에서 오버로드를 허용하지 않지만 .NET은 메서드에서이를 허용하므로 번호 2를 시도하십시오.
type Mon<'a> =
static member Bind(m : Option<'a>, f : ('a -> Option<'b>)) =
match m with
| None -> None
| Some x -> f x
static member Bind(m : List<'a>, f : ('a -> List<'b>)) =
List.map f m |> List.concat
let (>>=) m f = Mon.Bind(m, f)
주사위 없음. 이전에 제공된 유형 정보를 기반으로 고유 한 오버로드를 선택할 수 없습니다. 유형 주석을 추가하십시오.
나는 연산자를 인라인으로 만들려고했으나 여전히 같은 오류가 발생합니다.
그런 다음 >>=
연산자를 유형의 멤버로 만들 수 있다고 생각했습니다. 이 방법이 효과가있을 것이라고 확신하지만 기존 유형을 해킹 할 수 있다고 생각하지 않습니다. type Option<'a> with
으로 기존 유형을 확장 할 수 있지만 연산자를 확장자로 사용할 수 없습니다. 이 코드 내 마지막 시도였다
type Option<'a> with
static member (>>=) (m : Option<'a>, f : ('a -> Option<'b>)) =
match m with
| None -> None
| Some x -> f x
. "확장 회원 연산자 오버로드를 제공 할 수없는 대신 유형 정의의 일부로 연산자를 정의하는 것이 좋습니다." 굉장해.
다른 옵션이 있습니까? 나는 별도의 모듈에서 다른 모나드를위한 별도의 함수를 정의 할 수 있지만 같은 파일에서 둘 이상의 버전을 사용하려는 경우 지옥처럼 들린다.
@ 존 팔머 오, 죄송합니다. 요점은 Bind 메서드에 대해 두 개 이상의 오버로드가있는 것이 었습니다. 그런 다음 오류가 발생합니다. 나는 그 문제를 해결할 것이다. –
당신의 문제는 타입 생성자가 일반적인 (>> =) 합리적인 타입을 제공한다는 것입니다 (모나드가 친절합니다 * -> *) - 인라인 함수의 정적 제약은 이것 때문에 도움이되지 않습니다 너무 - 아니, 너는 운이 없어. – Carsten
때로는 연산자를 내 모듈 (종종 그냥 연산자라고도 함) 안에 랩핑합니다. 그래서 원하는 경우 MyMonad.Operators를 열거 나 MyMonad.Operators. >> =':(( – Carsten