Что «the» делает в Haskell и как его можно использовать?

#haskell

Вопрос:

В Хаскелле есть несколько определений типов, для the которых я не могу собрать воедино, чтобы понять это, имеют ли эти определения общую цель? если да, то в чем дело? то есть немного из Хоггла:

 the :: Eq a => [a] -> a

the :: HasAny sel s t a b => Lens s t a b

the :: (Eq a, Monad m) => SerialT m a -> m (Maybe a)
 

и т.д.

Комментарии:

1. Как и в (почти) каждом языке, модули в Haskell эффективно распределены по пространствам имен, поэтому создателям библиотек не нужно беспокоиться о том, что имена будут конфликтовать с именами в других библиотеках (или теми, которые еще предстоит написать). У нас в основном есть 3 отдельные функции, для которых авторы библиотеки (предположительно разные в каждом конкретном случае) решили the , что это подходящее название, и, вероятно, у них нет ничего общего, кроме этого имени. Если вы видите код, использующий один из них, операторы импорта должны прояснить, какой именно. (Этот вопрос кажется странным, чтобы задавать его, и я удивлен, что люди потрудились ответить и по голосам!)

2. @RobinZigmond странно это или нет, я рад, что спросил, вместо того, чтобы оставлять себя в сомнениях. Спасибо за ваш ответ.

Ответ №1:

Первый the «гарантирует», что все элементы в списке равны (следовательно Eq ), и в противном случае паникует. Его имя связано с тем, что он дает вам «единственный» элемент до равенства в списке.

 >>> the [1, 2, 3]
Error
>>> the [1, 1, 1]
1
 

Второй the используется для построения объектива (что-то, что может «извлечь» часть данных). Например, вы можете использовать the @"name" для создания объектива, который принимает name поле типа записи. Или the @Int извлечь единственное Int значение в данных, или the @3 получить третий компонент данных.

 data Human = Human
  { name    :: String
  , age     :: Int
  , address :: String
  }
  deriving (Generic, Show)
human :: Human
human = Human "Tunyasz" 50 "London"

>>> human ^. the @Int
50
>>> human ^. the @"name"
"Tunyasz"
>>> human ^. the @3
"London"
 

Третья функция аналогична первой, но работает для потока в библиотеке streamly , а не для списка, и возвращает None вместо паники, когда элементы не идентичны.

Комментарии:

1. Тогда нет никакой связи между этими функциями, просто у них одно и то же имя, определенное в разных пространствах имен ext, как указал @RobinZigmond?

Ответ №2:

Различные определения, что вы имеете в виду из разных модулей в разных пакетах: первый — GHC.Exts в base и в-третьих, с streamly в обоих из которых он используется, чтобы убедиться, что список содержит только одно значение, это значение возвращается; второй из Data.Generics.Product.Any В generic-lens , в котором он используется, чтобы выбрать что-то из объектива.