.net - Function in Discriminated Union Constraining the Type of a Generic Parameter -
i trying port haskell code f# , getting strange error don't know how around. have discriminated union function defined below:
type othertype = othertype1 of string | othertype2 of string type mytype<'a> = mysub1 of datetime * string * (float -> mytype<'a>) | mysub2 of 'a | mysub3 of datetime * string * (bool -> mytype<'a>)
later have function works on type such
let fun1 date mytype (myfun2: ('b -> mytype<'a>)) = match mytype | othertype1(string1) -> mysub1(date, string1, myfun2) | othertype2(string1) -> mysub3(date, string1, myfun2)
this constrains myfun2 type (float -> mytype<'a>). there way prevent happening , keep k generic?
the result second pattern match falls.
thank you.
update:
looking @ haskell code trying replicate think issue in haskell version othertype gadt , othertype1 becomes othertype double , othertype2 becomes othertype bool. myfun2 able perform both of functions. here code if interested.
data othertype othertype1 :: string -> othertype double othertype2 :: string -> othertype bool data mytype = mysub1 utctime string (double -> mytype a) | mysub2 | mysub3 utctime string (bool -> mytype a) myfun1 :: utctime -> othertype -> mytype myfun1 time o = myfun1' o mysub2 myfun1' :: othertype b-> (b -> mytype a) -> mytype myfun1' (othertype1 name) k = mysub1 time name k myfun1' (othertype2 name) k = mysub3 time name k
so guess question ask is, can gadts replicated in f#?
as far know, there no faithful way represent arbitrary gadts in f#. however, given structure of gadt , function you're writing, should possible use following (clunky) encoding:
// module witnessing equality of 2 types module eq = // opaque type equating 'a , 'b type eq<'a,'b> = private eq of ('a -> 'b) * ('b -> 'a) member eq.apply(v) = match eq | eq(f,_) -> f v member eq.unapply(v) = match eq | eq(_,g) -> g v // constructs eq<'a,'a> [<generalizablevalue>] let refl<'a> : eq<'a,'a> = eq(id,id) // not used, included completeness let sym (eq(f,g)) = eq(g,f) let trans (eq(f,g)) (eq(h,i)) = eq(f >> h, >> g) // ideally, we'd provide way lift eq<'a,'b> eq<f<'a>,f<'b>>, can't expressed f#'s type system type othertype<'a> = | othertype1 of eq.eq<'a,double> * string | othertype2 of eq.eq<'a,bool> * string // "smart" constructors let othertype1 s = othertype1(eq.refl, s) let othertype2 s = othertype2(eq.refl, s) type mytype<'a> = | mysub1 of datetime * string * (float -> mytype<'a>) | mysub2 of 'a | mysub3 of datetime * string * (bool -> mytype<'a>) let fun1 date mytype myfun2 = match mytype | othertype1(eq, string1) -> mysub1(date, string1, eq.unapply >> myfun2) | othertype2(eq, string1) -> mysub3(date, string1, eq.unapply >> myfun2)
Comments
Post a Comment