LINUX.ORG.RU

Ответ на: комментарий от pseudo-cat

Это sum type:

x :: a => Left x  :: Either a b  -- если терм x имеет тип a, то терм (Left x) имеет тип (Either a ?)
x :: b => Right x :: Either a b  -- если терм x имеет тип b, то терм (Right x) имеет тип (Either ? b)

Когда определяется тип через '|' то, по сути, определяется sum type. Для конечного числа типов это будет выглядеть так:

infixl 6 :+

data a :+ b = L a | R b

test2 :: Int :+ String -> Int
test2 (L _) = 1
test2 (R _) = 2

-- test2 $ L 1
-- > 1
--
-- test2 $ R "1"
-- > 2

test3 :: Char :+ Int :+ String -> Int
test3 (L (L _)) = 1
test3 (L (R _)) = 2
test3 (R _)     = 3

-- test3 $ L $ L 'a'
-- > 1
--
-- test3 $ L $ R 4
-- > 2
--
-- test3 $ R "4"
-- > 3

Для произвольного числа типов нужно привлечь классы типов (ad-hoc полиморфизм) и определить функцию typeOf :: (Typeable a) => a -> TypeRep тогда можно писать так:

test a | typeOf a == typeOf (undefined :: Char)    = 1
       | typeOf a == typeOf (undefined :: Integer) = 2
       | typeOf a == typeOf (undefined :: String)  = 3
       | otherwise                                 = 4

-- test '1'
-- > 1
--
-- test 2
-- > 2
--
-- test "3"
-- > 3
--
-- test 1.0
-- > 4

Т.е. вопрос сводится к наличию аналога Data.Typeable в F#.

quasimoto ★★★★
()

Возможно хорошим решением будут размеченные объединения, пример:

type MyType =
  | IsStr of string
  | IsInt of int

let t1 = IsStr "str"
let t2 = IsInt 32

let lst = [t1; t2]

let my_fun a =
  match a with
    | IsStr str -> printfn "string %A" str
    | IsInt a   -> printfn "integer %A" a

List.iter my_fun lst
Norgat ★★★★★
()

А то, что ты хочешь, делается так:

let my_fun2 (a: obj) =
  match a with
    | :? int as b -> 1
    | :? string as b -> 2
    | _ -> 3
Norgat ★★★★★
()
Ответ на: комментарий от Norgat

upd2

as b - ну нужно, если переменная потом не юзается.

Norgat ★★★★★
()

спасибо всем, в этом вроде разобрался, но у меня появились ещё несколько вопросов:

1) есть код

let getOutVertexesWithPaths_f (vset: Element * Element) graph = 
    let (vfrom, vnow) = vset
    graph
вызываю так(из C#): SearchModule.getOutVertexesWithPaths_f(new Pair<Element, Element>(v, v), schemGraph);

и получаю - ни одна из перегрузок метода «getOutVertexesWithPaths_f» не принимает «2» аргумента

2) как делать соответствие между своими типами и стандартными типами F#. В коде выше я в C# работаю с Pair<T1, T2>, а в F# хотелось бы использовать тип T1 * T2, где и как эти трансформации можно указать?

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от pseudo-cat
let getOutVertexesWithPaths_f (vset: Element * Element) graph = 
    let (vfrom, vnow) = vset
    graph

Эта функция имеет тип(упрощённо) A -> B -> C. А вызывать не из F# можно только функции с типом A -> C.

Нужно, если хочется вызывать getOutVertexesWithPaths_f из C#, делать так:

let getOutVertexesWithPaths_f (vset: Element * Element, graph) = 
    let (vfrom, vnow) = vset
    graph

По поводу:

2) как делать соответствие между своими типами и стандартными типами F#. В коде выше я в C# работаю с Pair<T1, T2>, а в F# хотелось бы использовать тип T1 * T2, где и как эти трансформации можно указать?

Статический метод C# со след. сигнатурой:

static void MyMember(int a, int b){..}

Отображается в F# в сигнатуру int*int -> unit. Каких-то `магических` преобразований нету, но всегда можно сделать обёртку в F#, если сильно хочется.

п.с. IEnumerable отображается в seq и наоборот, стандартные массивы C# отображаются в тип Array F#, на счёт List<T> из Collections.Generic не уверен(по поводу отображения в List F#), но в #seq<_> он точно отображается.

п.с.с. Pair самописный небось? Попробую поюзать стандартный Tuple<T1, T2>, возможно он отображается в T1*T2.

Norgat ★★★★★
()
Ответ на: комментарий от Norgat

Ах да, System.Collections.Generic.List<T> в F# называется ResizeArray<T>.

Norgat ★★★★★
()
Ответ на: комментарий от Norgat

A -> B -> C

не могли бы вы более подробно рассказать про эту запись, я так понимая, что A - это по сути Element * Element, B - это obj, а С - это B?

(vset: Element * Element, graph)

т.е. сделать один аргумент типа tuple вместо двух?

Каких-то `магических` преобразований нету

так я на это и не надеюсь поэтому и хочу какое-то соответствие задать, возможно через type

Pair самописный небось?

да

pseudo-cat ★★★
() автор топика
Ответ на: комментарий от pseudo-cat

> не могли бы вы более подробно рассказать про эту запись, я так понимая, что A - это по сути Element * Element, B - это obj, а С - это B?

Всё достаточно просто. A -> B - это обычная математическая запись отображения множества A в множество B. Скажем в каком-нибудь Си подобном языке она соотв. скажем сигнатуре функции вида: float my_fun(int a).

Теперь нужно указать на один момент. Ф-ция в функциональном ЯП, вообще говоря, это именованая лябмда, т.е.

let my_fun x = x+2

эквивалентно

let my_fun = fun x -> x+2

а на языке лямбда функций это запишется my_fun = \x. x+2 (\ - схемотичное написание значка лямбда).

Теперь возьмём запись my_fun2 = \x.\y. x+y, которую обычно записывают в виде \x y. x+y. Сразу скажу что такая ф-ция уже имеет сигнатуру A->B->C (если не уточнять типы). Что это означает? А это означает, что my_fun2 2 будет функцией равной \y. 2+y. На F# это запишется:

let my_fun2 = fun x -> fun y -> x+y

или

let my_fun2 x y = x+y

Так вот, сигнатура A->B->C не совместима со стандартной дотнетовской, т.к. там есть обёртки необходимые для генерации функций одной переменной из my_fun2.

В сети валяется перевод MIT'овских лекций по языку ML, вот в начале там даются основы лямбда исчисления. Их бы оч. не плохо бы почитать, чтобы лучше представлять, что такое лямбды (для систематизации знаний).

так я на это и не надеюсь поэтому и хочу какое-то соответствие задать, возможно через type

Тут есть одно правило - хочешь чтобы функция вызывалась из C#, делай её только в виде let my_fun (a, b, c, ...) = ... где a,b,c и т.д. типы не специфичные для F# (или имеют общий для .Net интерфейс).

Norgat ★★★★★
()

В F# есть Choice{такой-то}of{столько-то}. Уже готово.

dave ★★★★★
()

А именно

val f: Choice<int, string> -> int

let f = function
    | Choice1Of2 _ -> 1
    | Choice2Of2 _ -> 2
dave ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.