简体   繁体   中英

Can the F# type system do this?

I have a lot of various types that have a common purpose, but little else in common. For the sake of explanation, they might as well be along the lines of:

type blah<'a> = Blah of 'a

type huha<'a> = Huha of 'a

I often need to repeat a large chunk of boilerplate that could go inside a function along the lines of:

let f (x:something<int>) (g:something<char> -> float) : float =

But that would require somehow enforcing that the two somethings in the type are the same. In other words, I would like to be able to call the function f as:

f (Blah 1) (fun (b:blah<float>) -> .... )
f (Huha 1) (fun (b:huha<float>) -> .... )

Obviously, a trivial solution is to create a discriminated union of all the types function f could possibly take, and make every g (ie f's second argument) check it got whatever type it expected. But that means having a massive type that causes the universe to recompile every time anything changes, and it's not like checking types at runtime helps a great deal either.

So, can someone please see a way of doing what I want in a typesafe way? Many thanks.

As far as I understand, you cannot do this directly in F#.

But maybe operator overloading will help. You would have to implement f for every type, though. But maybe you can delegate to a common implementation.

A code example for operator overloading, ensuring the right types:

type T<'a> =
   | T of 'a
   static member (.+.) (l:T<int>, r:T<char> -> float) = 42.0

type U<'a> =
   | U of 'a
   static member (.+.) (l:U<int>, r:U<char> -> float) = 13.1


let ft (t:T<char>) = 42.0

let fu (t:U<char>) = 42.0

let t = T 42 .+. ft
let u = U 13 .+. fu

// does not compile:
let wrong = T 42 .+. fu

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM