PureScript — что такое новый тип?

Руководство PureScript определяет упражнение следующим образом:

Define a Show instance for Point. Match the same output as the showPoint function from the previous chapter. Note: Point is now a newtype (instead of a type synonym), which allows us to customize how to show it. Otherwise, we'd be stuck with the default Show instance for records. (https://book.purescript.org/chapter6.html)

Однако не предоставляется никакой информации о том, что такое Новый тип.

Что такое новый тип? Для чего это? Почему здесь работает, а не печатает?

Кажется, вы пропустили это в главе 5!

Robin Zigmond 09.04.2022 18:11
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
1
27
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Newtype — это просто оболочка для одного (или нескольких) типов. Обычно мы используем его для предоставления предопределенного или уже доступного типа в качестве нового типа.

Есть много полезных вещей, которые мы можем делать с newtype, одна из них указана автором в главе, которой вы поделились выше.

Когда вы указываете

type Point = 
  { x :: Number
  , y :: Number
  }

На самом деле вы не можете определить свои собственные экземпляры класса типов (например, показать экземпляр), поскольку Point — это просто синоним типа для типа записи, который предопределен в модуле Prim из purescript.

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

Вы также можете использовать его для создания более строгих значений. Например, вы хотите создать имя типа, когда его размер меньше 6, вы хотите подчеркнуть ошибку. Итак, что вы делаете,

type Name = Either String String

затем вы создаете функцию,

type Name = Either String String 
createName' :: String -> Name 
createName' name 
 | (length name) >= 6 =   (Right name)
 | otherwise          =   (Left "Invalid Name")

ты счастлив сейчас. Но это не мешает другому разработчику делать что-то вроде

 myName :: Name
 myName = (Right "a")

Итак, как вы можете позволить Name создаваться только функцией?

  1. Только импортируя функцию.
  2. Не импортируя Name

Проблема в том, что вы не можете сделать второй шаг, так как Name — это просто синоним типа.

name :: Name такое же, как name :: Either String String

поэтому вы оборачиваете Either String String новым типом

 newtype StrictName = MkName (Either String String)
 createName :: String -> StrictName 
 createName name 
    |  (length name) >= 6 =  MkName (Right name)
    |  otherwise          =  MkName (Left "Invalid Name")

теперь вы импортируете только функцию и StrictName (без ее конструктора) например

module Data.MyTypes.Name
(StrictName,createName)

Теперь нет другого способа создать значение StrictName без использования функции createName. (это также возможно с типами ADT, но я предпочитаю новый тип)

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

Note : Newtype adds runtimes overhead as theres one more wrapper around the original type.

Откуда вы взяли последнюю цитату о накладных расходах времени выполнения. Мое понимание, основанное на большем опыте работы с Haskell, чем с Purescript, состоит в том, что новые типы не добавляют НИКАКИХ накладных расходов во время выполнения, и это также заявил в книге Purescript. Весь смысл в разрешении типов только с одним конструктором и одним полем заключается в том, чтобы разрешить преобразование без потерь из одного в другое, что означает, что компилятор может легко удалить преобразование.

Robin Zigmond 09.04.2022 18:14

@RobinZigmond теоретически может, но на практике не всегда так. PureScript намного менее агрессивен, чем Haskell, когда дело доходит до оптимизации и встраивания, что имеет значение для встроенных функций (например, T 1 > T 2 будет скомпилировано как Ord_T.greater(1)(2), а 1 > 2 будет скомпилировано как 1 > 2, что на одно выделение кучи и два вызова функций меньше) и второго порядка ситуации, напр. для T <$> [1,2,3] вызов map не будет устранен. Это не значит, что нет планов по улучшению этого, но сейчас это реальность.

Fyodor Soikin 09.04.2022 20:09

спасибо @FyodorSoikin - я так понимаю, что эта цитата из книги: «На самом деле значения нового типа имеют то же представление во время выполнения, что и базовый тип, поэтому нет накладных расходов во время выполнения». просто ложно, по крайней мере, в ситуации, которую вы описали?

Robin Zigmond 09.04.2022 20:40

Да, почти неверно.

Fyodor Soikin 09.04.2022 20:49

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