Изучение «дискриминационных объединенных» типов F#, как аналога «наследственной иерархии», в школьном курсе информатики

№98-1,

педагогические науки

В статье рассматривается вопрос изучения "дискриминационных объединяющих" типов языка F#, в школьном курсе информатики. Приводятся примеры, в которых учащиеся реализуют алгоритмически сложные конструкции, для решения поставленных проблемных задач.

Похожие материалы

Одним из наиболее важных и продолжительных разделов программы обучения информатике в общеобразовательной школе является обучение одному из языков программирования. При этом зачастую предполагается изучение алгоритмического языка, так как обучение языку преследует цель освоения алгоритмических конструкций и применение их для построения алгоритмов решения учебных задач. В современном программировании практически выходят из употребления языки чисто алгоритмического типа. Все большее внимание уделяется языкам объектно-ориентированным.

Особый интерес, для изучения в школьном курсе информатики, представляет собой язык F#. Структура F# во многом схожа со структурой OCaml с той лишь разницей, что F# реализован поверх библиотек и среды исполнения .NET. Код на языке F# является безопасным в отношении типов, часто бывает более компактным, чем аналогичный код C#, за счёт вывода типов. В F# действует строгая типизация (ошибки определяются на этапе компиляции), неявные преобразования типов полностью отсутствуют, что полностью исключает ошибки, связанные с приведением типов. Язык насыщен рядом возможностей, таких как упрощенный синтаксис, обобщённое программирование и функции высших порядков, которые позволяют писать абстрактные обобщённые алгоритмы, которые управляют параметризованными структурами данных.

Являясь в основном функциональным языком, он широко поддерживает императивную, объектно-ориентированную парадигмы. Особенности языка дают возможность рассматривать некоторые аспекты программирования, совершенно в другом контексте. Интересной становится задача рассмотрения понятия «наследования», в «императивном контексте».

Рассмотрев с учащимися понятия типов, принципов работы с языком в императивной и функциональной реализации, необходимо уделить время исследованию таких синтаксических конструкций как кортежи и записи. После закрепления основных структур языка следует рассмотреть понятие «дискриминационный объединённый» тип как суммы пользовательских и стандартных типов, при этом провести параллели с объектно-ориентированными конструкциями.

Кортежи и записи являются примерами создания новых типов путем «сбора» существующих типов вместе. Другим способом создания новых типов становится «суммирование» существующих типов.

Возникает задача по определению функции, которая работает, например, с целыми числами или логическими значениями, возможно, чтобы преобразовать их в строки. Но при этом, необходимо быть строгими и не принимать никакого другого типа (например, вещественные числа или строки).

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

В F # тип суммы называется «дискриминационным объединенным» типом. Каждый тип компонента должен быть помечен меткой, для того чтобы их можно было разделить («дискриминировать»). Метки могут быть любыми идентификаторами, но должны начинаться с буквы верхнего регистра.

Пример определения:

type IntOrBool =  | I of int | B of bool

«I» и «B» — это просто произвольные метки. Для небольших типов мы можем поместить определение в одну строку: type IntOrBool = I of int | B of bool.

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

type Person = {first:string; last:string} type IntOrBool = I of int | B of booltype MixedType =  | Tup of int * int // кортеж из двух целочисленных значений | P of Person    // тип запись | L of int list   // список | U of IntOrBool  // объединенный тип

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

type IntOrBool = Int32 of Int32 | Boolean of Boolean

Этот стиль «дублирования имен» на самом деле довольно распространен.

Чтобы создать значение созданного «дискриминационного объединенного» типа, используется «конструктор», который ссылается только на один из возможных случаев объединения.

type IntOrBool = I of int | B of boollet i = I 99  // use the "I" constructor// val i : IntOrBool = I 99let b = B true // use the "B" constructor// val b : IntOrBool = B true

Если конструктор имеет более одного «параметра», создается значение посредством вызова функции:

type Person = {first:string; last:string}type MixedType = | Tup of int * int | P of Personlet myTup = Tup (2,99)  // конструктор для картежа// val myTup : MixedType = Tup (2,99)let myP = P {first="Al"; last="Jones"} // конструктор для записи// val myP : MixedType = P {first = "Al";last = "Jones";}

На основании принципа создания «дискриминационных объединенных» типов, с учащимися решается ряд задач, в которых данный тип выступает как «родительский» объединяющий «дочерние» типы.

Рассмотрим варианты решений одной из базовых задач, предложенные учащимися.

Задание. Создайте тип «Животное» (слон, жираф, бегемот, обезьяна с картежами параметров животных). Создайте экземпляры разных животных и составьте из них список. Создайте методы, находящие самый высокий рост среди животных, имя самого маленького животного, печатающие информацию о животном. Продемонстрируйте использование типа.

Решение 1.

open Systemtype Animals =  | Elephant of string * double * double //имя * рост * вес  | Giraffe of string * double * double  //имя * рост * вес  | Hippo of string * double * double   //имя * рост * вес  | Monkey of string * double * double  //имя * рост * весlet MaxHeight list =  let mutable max : double = -1.0  for i in list do    match i with    | Elephant (_, h, _) -> if h > max                then max <- h    | Giraffe (_, h, _) -> if h > max                then max <- h    | Hippo (_, h, _) -> if h > max               then max <- h    | Monkey (_, h, _) -> if h > max               then max <- h  maxlet MinAnimal list =  let mutable min : double = Double.MaxValue  let mutable name : string = ""  for i in list do    match i with    | Elephant (n, _, w) -> if w < min                then min <- w                   name <- n    | Giraffe (n, _, w) -> if w < min                then min <- w                  name <- n    | Hippo (n, _, w) -> if w < min               then min <- w                 name <- n    | Monkey (n, _, w) -> if w < min               then min <- w                  name <- n  namelet Print a =  match a with  | Elephant (n, h, w) -> String.Format("Слон {0}, рост: {1}, вес: {2}", n, h, w)  | Giraffe (n, h, w) -> String.Format("Жираф {0}, рост: {1}, вес: {2}", n, h, w)  | Hippo (n, h, w) -> String.Format("Бегемот {0}, рост: {1}, вес: {2}", n, h, w)  | Monkey (n, h, w) -> String.Format("Обезьяна {0}, рост: {1}, вес: {2}", n, h, w)let e = Elephant("El", 200.0, 1500.0)let g = Giraffe("Gr", 1000.0, 1000.0)let h = Hippo("Hp", 200.0, 2000.0)let m = Monkey("Mn", 50.0, 20.0)let list = [|e; g; h; m|]let max = MaxHeight listlet min = MinAnimal listConsole.WriteLine("Самое высокое животное: " + max.ToString())Console.WriteLine("Самое маленькое хивотное: " + min.ToString())Console.WriteLine(Print g)Console.WriteLine(Print h)m)

Решение 2.

open System type Animal =  | Elephant of string * double  | Giraffe of string * double  | Hippo of string * double  | Monkey of string * double let PM (a : Animal) : string * double =  let Result =    match a with    | Elephant(n,a1) -> (n,a1)    | Giraffe(n,a1) -> (n,a1)    | Hippo(n,a1) -> (n,a1)    | Monkey(n,a1) -> (n,a1)  Result let MaxHeght (lst: (Animal list)) =  let res = List.sortBy(fun a -> snd (PM a)) lst  printfn "%s" ("Наибольший рост: " + (snd (PM (res.Item(res.Length — 1)))).ToString()) let SmallAnimal lst =  let res = List.sortBy(fun a -> snd (PM a)) lst  let out = fst (PM (res.Item(0)))  printfn "%s" ("Наименьший рост у " + out) let PrintA(a:Animal) =  let textResult =    match a with    | Elephant (name, height) -> "Имя: " + name + " Рост: " + height.ToString()    | Giraffe (name, height) -> "\nИмя: " + name + " Рост: " + height.ToString()    | Hippo (name, height) -> "\nИмя: " + name + " Рост: " + height.ToString()    | Monkey (name, height) -> "\nИмя: " + name + " Рост: " + height.ToString()  printfn "%s" textResult [<EntryPoint>]let main argv =  let a1 = Elephant ("Слон", 20.);  let b1 = Giraffe ("Жираф", 50.);  let c1 = Hippo ("Бегемот", 10.);  let d1 = Monkey ("Обезьяна", 5.);  let res = [a1; b1; c1; d1]  MaxHeght res  SmallAnimal res  for i in res do    PrintA i  Console.ReadLine() |> ignore   0 // возвращение целочисленного кода выхода

Таким образом, «дискриминационный объединенный» тип выступает как «родительский» суммирующий тип. При этом существует возможность в рамках данного типа объединять совершено разнообразный набор типов, что невозможно в рамках объектно-ориентированного подхода. При работе над решением аналогичных задач, учащиеся применяют свои знания по конструированию экземпляров типов, поиску и фильтрации данных в списках, отбору данных по соответствию и использованию функций. При проведении регулярных занятий по программированию, подготовке учащимся ряда взаимосвязанных систематически организованных занимательных заданий, создаются наиболее благоприятные условия для формирования логического и алгоритмического мышления, воспитание самостоятельности, проявляющаяся в активном и инициативном поиске решения задач, в глубоком и всестороннем анализе их условий.

Список литературы

  1. Магомедов Р.М. Объектно-ориентированное программирование -инновационный путь в программирование в школе//Известия Чеченского государственного педагогического института. 2009. № 2.
  2. Векслер В.А. Программирование на языке f# в школьном курсе информатики / Сборник: Информационные технологии в образовании "ИТО-Саратов-2016" Материалы VIII Международной научно-практической конференции. 2016. С. 36-40.
  3. Валиева А.М Проблемы развития алгоритмического мышления младших школьников в условиях информатизации образования // URL: https://scienceforum.ru/2013/article/2013007474 (доступ свободный, 16.02.2019).