Ограничение аргумента на значение Int

#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, когда он используется. Это просто дополнительная сложность.