Сравнение пустых списков в кортеже в Haskell

Мне пришлось написать свою собственную функцию распаковки. Теперь мне нужно написать примеры. Но я не могу работать с пустыми списками:


example_unzip_1 = unzip [] == ([],[])

Я пробовал несколько вещей, но больше всего я ожидал, что это сработает:


example_unzip_1 = unzip []::[(a,b)] == ([],[])::([a],[b])

Я знаю, что ошибка связана с типами, но я не знаю, что делать.

редактировать

Я обновил выражения, потому что комментарии показали, что я недостаточно ясен.

example_unzip_1 должно быть истинным.

и определение функции:

DEFINITION

> unzip [] = ([],[])
> unzip ((a,b):xs) = (a:as, b:bs)
>   where (as, bs) =  unzip xs

В Haskell вы определяете новую сущность с помощью одного знака «=». Это известно как оператор присваивания. Нравится: newEntity = definition of new entity ; двойной знак равенства "= = " используется только для проверки равенства двух уже определенных объектов, как в языках C и C++.

jpmarinier 10.12.2020 12:10

Читая ваш пост, я не могу точно сказать, является ли ваш код реализацией вашего распаковки или двумя примерами, которые, по вашему мнению, должны быть правдой. Можете ли вы опубликовать код своей функции вместе с сигнатурой типа, которая у нее есть?

Marc Talbot 10.12.2020 12:27
unzip [] = ([],[]) с одним знаком равенства — это вполне допустимая строка кода. Теперь вам также нужно другое уравнение для обработки непустых входных списков.
chi 10.12.2020 12:50

Извините ребята. Мой вопрос показался недостаточно ясным.

peni4142 10.12.2020 13:23
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Если вы введете unzip [] == ([],[]) в GHCi, он будет правильно оценен как True, но когда вы добавите строку example_unzip_1 = unzip [] == ([],[]) в файл и попытаетесь открыть его, вы получите ошибку типа. Почему это? На техническом жаргоне GHC это связано с «ограничением мономорфизма», но на практике это означает, что GHC не знает, какой тип списков вы используете.

В GHCi интерпретатор автоматически делает некоторые настройки по умолчанию за вас. Если вы введете число, например 3, оно распечатается 3. Но если вы спросите тип 3 с :t 3, вы увидите, что он говорит 3 :: Num p => p. Итак, если GHCi знает только то, что 3 — это тип, являющийся экземпляром Num, то как он смог это показать? И почему он не показывает это как 3.0, если вы ввели Float? Что ж, в отсутствие дополнительной информации GHCi «по умолчанию» использует тип Integer и использует экземпляр Show для Integer. Когда вы вводите unzip [] == ([],[]), по умолчанию также устанавливаются типы списков, присваивая им конкретный тип и экземпляр Eq.

Вы на правильном пути со второй попыткой (то есть example_unzip_1 = unzip []::[(a,b)] == ([],[])::([a],[b])), но здесь есть две проблемы. Во-первых, GHC немного привередлив к переменным типа, и в этом случае, поскольку вы не ввели свои переменные типа с ключевым словом forall (что также требует использования некоторых языковых расширений, вероятно ScopedTypeVariables), GHC на самом деле не понимает, что a слева совпадает с a справа. Но несмотря на это, GHC по-прежнему не будет знать, какие фактические типы использовать при проверке на равенство!

Способ исправить это — использовать фактические конкретные типы. Например, вы можете написать:

example_unzip_1 = unzip []::[(Int,())] == ([],[])::([Int],[()])

Это правильно напечатает check. На самом деле, из-за хорошего вывода типов GHC вам нужна только одна аннотация типа, поэтому вы можете упростить это до:

example_unzip_1 = unzip []::[(Int,())] == ([],[])

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