Соответствие шаблону F # для типов кортежей

Вы можете использовать следующий запрос для MYSQL:

SHOW columns FROM your-table;

Ниже приведен пример кода, который показывает, как реализовать выше синтаксис в php для перечисления имен столбцов:

$sql = "SHOW COLUMNS FROM your-table";
$result = mysqli_query($conn,$sql);
while($row = mysqli_fetch_array($result)){
    echo $row['Field']."
"; }

Подробнее о выходе SHOW COLUMNS FROM TABLE: MySQL Refrence.

10
задан Bruno Reis 6 February 2010 в 19:24
поделиться

4 ответа

Ваш код не работает, потому что F # обобщает тип аргументов до параметра типа. Я думаю, вы не можете динамически проверить, можно ли преобразовать тип 'a *' b в тип MyType1 * MyType2 (хотя меня это немного сбивает с толку). В любом случае, вы можете написать функцию, которая принимает два аргумента типа obj и проверяет их отдельно, используя два :? паттернов:

type MyType1 = A | B of float 
type MyType2 = C | D of int

let func (x:obj) (y:obj) = 
    match (x, y) with 
    | (:? MyType1 as x1), (:? MyType1 as x2) -> 
        printfn "%A %A" x1 x2
    | _ -> 
        printfn "something else" 

func A (B 3.0) // A B 3.0
func A (D 42)  // something else

В любом случае, было бы интересно узнать, почему ты хочешь это сделать? Может быть лучшее решение ...

РЕДАКТИРОВАТЬ (2) Итак, из всех 4 двухэлементных комбинаций T1 и T2 вам нужна функция, которая можно взять 3. Это правильно ( T1 * T1 , T1 * T2 и T2 * T2 )? В этом случае вы не сможете написать полностью безопасную каррированную функцию, потому что тип второго аргумента будет «зависеть» от типа первого аргумента (если первый аргумент имеет тип T2 , то второй аргумент также должен быть T2 (в противном случае он также может быть T1 )).

Вы можете написать безопасную функцию без каррирования, которая принимает аргумент следующего типа:

type MyArg = Comb1 of T1 * T1 | Comb2 of T1 * T2 | Comb3 of T2 * T2

Тип функции будет MyArg -> string . Если хотите каррированная функция, вы можете определить тип, который позволяет вам использовать либо T1 , либо T2 как первый и второй аргумент.

type MyArg = First of T1 | Second of T2

Тогда ваша каррированная функция будет MyArg -> MyArg -> string . Но обратите внимание, что если одна комбинация типов аргументов недопустима (если я правильно вас понял, T2 * T1 не должно быть разрешено). В этом случае ваша функция просто должна будет выбросить исключение или что-то в этом роде.

15
ответ дан 3 December 2019 в 16:29
поделиться

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

Эта функция должна решать, какая из opXY to call, properly downcasting типы.

Это один из тех случаев, когда правильный ответ не "вот как это делается", а "не делай так". Нет никакого реального преимущества в использовании F#, если вы не собираетесь придерживаться его идиом и проверки типов.

С моей точки зрения, если ваши типы настолько похожи, то они должны быть объединены в один тип:

type MyType = A | B of float | C | D of int

За исключением этого, вы можете обернуть ваши два типа в другой тип:

type composite =
    | MyType1Tuple of MyType1 * MyType1
    | MyType2Tuple of MyType2 * MyType2

Другой слой идирекции никогда никому не навредит. Но, по крайней мере, теперь ваши клиенты могут обернуть объекты другим типом, не теряя при этом безопасности типа.

И за исключением всего этого, вы можете обернуть два отдельных метода для разных типов.

3
ответ дан 3 December 2019 в 16:29
поделиться

Существуют, по сути, три различных способа добиться этого.

Первый - пожертвовать статическим набором текста, повысив его до obj, как вы и предлагали:

let func x y =
  match box x, box y with
  | (:? MyType1 as x), (:? MyType1 as y) ->
      ...

Это практически всегда ужасное решение, так как приводит к введению ненужных проверок типов исполнения:

  | _ -> invalidArg "x" "Run-time type error"

Только место, где я хорошо видел эту работу, - это библиотечный код, разработанный специально для пользователей для вызова из F# интерактивных сессий, где одновременно эффективно происходят ошибки типа компиляции и типа исполнения, а динамический набор текста может быть более лаконичным. Например, наша библиотека F# for Visualization позволяет пользователю попытаться визуализировать любое значение любого типа, используя данную технику для вызова пользовательских процедур визуализации для различных (известных) типов (читайте подробнее).

Второе решение - это замена двух отдельных типов на один:

type MyType1 = A | B of float | C | D of int   

Третье решение - это введение нового типа, который унифицирует только эти два типа:

type MyType = MyType1 of MyType1 | MyType2 of MyType2
6
ответ дан 3 December 2019 в 16:29
поделиться

Это очень подозрительно пахнет, вам следует описать более крупный контекст проблемы, поскольку, похоже, вам не следует попадать в такую ​​ситуацию. Тем не менее:

type MyType1 = A | B of float 
type MyType2 = C | D of int 

// imagine this adds floats, and C -> A (=0.0) and D -> B
let DoIt x y =
    match x, y with
    | A, A -> 0.0
    | A, B z -> z
    | B z, A -> z
    | B z1, B z2 -> z1 + z2

let Convert x =
    match x with
    | C -> A
    | D i -> B (float i)

let Func (x:obj) (y:obj) =
    match x, y with
    | (:? MyType2 as xx), (:? MyType2 as yy) -> DoIt (Convert xx) (Convert yy)
    | (:? MyType1 as xx), (:? MyType2 as yy) -> DoIt xx (Convert yy)    
    | (:? MyType2 as xx), (:? MyType1 as yy) -> DoIt (Convert xx) yy
    | (:? MyType1 as xx), (:? MyType1 as yy) -> DoIt xx yy    
    | _ -> failwith "bad args"
1
ответ дан 3 December 2019 в 16:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: