Как обеспечить выполнение условий выполнения для данных в Haskell? - PullRequest
0 голосов
/ 11 декабря 2018

Я хочу определить функцию f [Int] -> Int, где f равно сумме элементов в списке, если длина списка является идеальным квадратом и не определена в противном случае.Какой идиоматический способ сделать это в Haskell?

На императивном языке я бы добавил строку с эффектом assert sqrt(len(xs)) is integer, чтобы сгенерировать исключение для неопределенных случаев.В строго типизированном функциональном языке, таком как Haskell, вы хотите встроить неопределенные условия в систему типов, однако это не может быть выполнено здесь, поскольку нет типа «список длины идеального квадрата».

Я быпредпочитают, чтобы программа остановилась с ошибкой в ​​неопределенном случае, а не возвращала функцию Nothing.

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Я бы предпочел, чтобы программа остановилась с ошибкой в ​​неопределенном случае, а не возвращала функцию Ничего.

Стандартный и идиоматический способ сделать это, безусловно,верните Maybe Int вместо того, чтобы делать то, что вы предпочитаете делать.

Если вы спрашиваете, как вызвать ошибку из чистого кода, вы можете сделать

f ... = error "oops it wasn't a perfect square"

Другая возможность состоит в том, что ваш ввод [Int] неправильного типа.Возможно, то, что вы хотите, это список, который гарантированно имеет степень двух длин.В этом случае вы можете создать умный конструктор (функция, которая является единственным способом создания PowerOfTwoList a и которая выполняет проверку).Вы также можете использовать какой-то вектор с индексом длины, где натуральный уровень типа является степенью двойки (т. Е. Длина списка представлена ​​в типе и также корректна по построению)

0 голосов
/ 11 декабря 2018

Если вы хотите говорить об этом формально, это может быть хорошей возможностью использовать умный конструктор .

module PSqList
    ( PSqList   -- constructor *not* exported
    , fromList
    )
where

newtype PSqList a = PSqList [a]
    deriving (Functor, Foldable)

fromList :: [a] -> Maybe (PSqList a)
fromList xs
    | isPerfectSquare (length xs) = Just (PSqList xs)
    | otherwise = Nothing

Затем, когда вы используете модуль PSqList, вы можететолько создавайте PSqList с идеальной длиной квадрата.

Немного странно использовать целый модуль для чего-то подобного;может быть, вы хотите более общую систему отслеживания инвариантов.Это область языка с типизированной зависимостью, такого как Agda в целом, но в Haskell есть прекрасная середина, показанная в функциональной жемчужине Ghosts of Departed Proofs .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...