#haskell #constraints
#haskell #ограничения
Вопрос:
Я пытаюсь объявить функцию, в которой числовым аргументом может быть только Int
.
Я пишу функцию, которая будет отбрасывать каждый n
-й элемент списка. Я использую арифметику по модулю, но mod
функция будет принимать только тип Int
, и я не могу понять, как гарантировать, что мой номер удовлетворит этому.
Мой код выглядит следующим образом:
dropEvery :: (Num n, Eq n) => n -> [a] -> [a]
dropEvery m list = [list !! i | i <- [1 .. length list], i `rem` m /= 0]
Я запустил :info mod
и заменил Num n
на Real n, Enum n and Integral n
(все ограничения, которые я вижу в выходных данных), но это все еще не гарантирует компилятору, что n
будет Int
.
Я уверен, что есть решения этой проблемы, которые не используют такой императивный подход, но я хотел бы воспользоваться этой возможностью, чтобы узнать немного больше о том, как типы и ограничения работают в Haskell, решая эту проблему напрямую.
Комментарии:
1. Почему бы вам не определить его как
Int -> [a] -> [a]
?
Ответ №1:
Вам просто нужно использовать фактический тип Int
вместо использования ограничений (Num n, Eq n)
. (Обратите внимание, что Haskell использует индексацию списка на основе 0, поэтому мне пришлось добавить -1
, чтобы он работал правильно.)
dropEvery :: Int -> [a] -> [a]
dropEvery m list = [list !! (i-1) | i <- [1 .. length list], i `rem` m /= 0]
main = print $ dropEvery 3 [1..20]
Если вы хотите избежать !!
, вы также можете избежать явного определения длины списка, используя zip
который заменяет ваше понимание списка на
[ l | (l,i) <- zip list [0..], (i 1) `rem` m /= 0]
Комментарии:
1. Если вы действительно, действительно хотите, чтобы подпись казалась полиморфной, но хотите ограничить
n
бытиеInt
, используйте~
:dropEvery :: (n ~ Int) => ...
. (ПотребностиLANGUAGE GADTs
. расширение.)2. Um. Почему zip с
[0..]
затем добавьте 1 вместо простого архивирования с[1..]
?3. @Carl Я хотел подчеркнуть, что индексы списка основаны на 0, даже если в этом примере это не имеет значения. Но, может быть, вас интересует PPCG.SE ? 🙂
4. Вообще не интересуюсь code golf. Меня интересует ясность и прямота. Если вы хотите связать число 1 со значением, свяжите 1 со значением. Не связывайте с ним 0, а затем добавляйте 1, когда он используется. Это просто дополнительная сложность.