Вы можете использовать следующий запрос для 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.
Ваш код не работает, потому что 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
не должно быть разрешено). В этом случае ваша функция просто должна будет выбросить исключение или что-то в этом роде.
У меня два одинаковых, но разных, типы. Я могу очень легко конвертировать один набирать на клавиатуре. Я хочу определить двоичная операция, которая будет действовать сущности этих типов, но я бы хотел... подвергать одну операцию клиент.
Эта функция должна решать, какая из 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
Другой слой идирекции никогда никому не навредит. Но, по крайней мере, теперь ваши клиенты могут обернуть объекты другим типом, не теряя при этом безопасности типа.
И за исключением всего этого, вы можете обернуть два отдельных метода для разных типов.
Существуют, по сути, три различных способа добиться этого.
Первый - пожертвовать статическим набором текста, повысив его до 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
Это очень подозрительно пахнет, вам следует описать более крупный контекст проблемы, поскольку, похоже, вам не следует попадать в такую ситуацию. Тем не менее:
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"