F#: сопоставить функцию по ее сигнатуре

У меня есть этот вопрос о сопоставлении функций по своей подписи. Я спрашиваю об этом в учебных целях, и я понимаю, что есть много способов обойти это.

Предположим, что в F# у меня есть следующие аналогичные типы:

type T1 = int * int * int
type T2 = {a:int ; b:int; c:int}

И преобразование между ними так же тривиально, как

let convert p =
    match p with
    |(x,y,z) -> {a = x; b = y; c = z}

Предположим также, что у меня есть обширная библиотека функций, которые были написаны для использования с T1 что я теперь хочу использовать с T2, такие как:

let addT1 a b =
    match a, b with
    |(x1,y1,z1),(x2,y2,z2) -> (x1 + x2, y1 + y2, z1 + z2)

let negT1 = 
    function
    |(x,y,z) -> (-x,-y-z)

let offset a i =
    match a with
    |(x,y,z) -> (x + i, y + i, z + i)

Как видите, все функции основаны на T1 но может получить несколько параметров T1 или параметры других типов.

Я знаком с этим, ведьма позволяет мне сопоставить любую функцию (f: int * int * int -> 'a) к функции (g: T2 -> 'a):

let funcOfT2 f = fun (t:T2) -> f (t.a, t.b, t.c)

Но в случае addT1например, это не работает из-за второго параметра:

val addT1 : int * int * int -> int * int * int -> int * int * int
val (funcOfT2 addt1) : (T2 -> int * int * int -> int * int * int)

Итак, чтобы использовать функцию как funcOfT2 Я должен был бы использовать это так, ведьма непрактична

let p1 = {a = 1; b = 2; c = 3}
let p2 = {a = 2; b = 3; c = 4}
let x = funcOfT2 (funcOfT2 addT1 p1) p2
val x = int * int * int = (3,5,7)

Я мог бы также сделать локальную версию каждой функции T1 прохождение необходимых сумм funcOfT2 или использовать convert каждый раз, когда я использую функцию T1, но я считаю, что это было бы действительно непрактично и сделать загроможденный код.

Есть ли в любом случае совпадение сигнатуры функции, чтобы я мог преобразовать любую функцию, которая принимает любой T1 в функции T2?

Моя идея была примерно такой: она не работает по многим причинам, но я думаю, что она может служить примером того, что я хотел. Есть ли способ сделать это?

let rec myDream f =
    match f with
    |(g: T1 -> 'a) -> fun (t:T2) rest -> fOfT2 (g (convert t)) rest
    |(g: 'b -> 'c) -> fun x y -> fOfT2 (g x) y
    |(g: 'd) -> g d

0 ответов

Другие вопросы по тегам