Проблема с арифметической последовательностью c в Списке Haskell - PullRequest
2 голосов
/ 04 марта 2020

Я пишу функцию, подобную этой:

constGrid :: a -> [[a]]
constGrid c = take 3 [take 3 [i,i ..] | i <- [c,c ..]]

И я вызываю ее с помощью:

print(constGrid 'a')

Она должна печатать

["aaa","aaa","aaa"]

или любую замена целым или логическим значением 'a'.

Когда я комментирую первую строку, она работает, но когда я ее открываю, выдает ошибку, подобную этой:

[1 of 1] Compiling Main             ( test.hs, test.o )

test.hs:17:46: error:
• No instance for (Enum a)
    arising from the arithmetic sequence ‘c, c .. ’
  Possible fix:
    add (Enum a) to the context of
      the type signature for:
        constGrid :: a -> [[a]]
• In the expression: [c, c .. ]
  In a stmt of a list comprehension: i <- [c, c .. ]
  In the second argument of ‘take’, namely
    ‘[take 3 [i, i .. ] | i <- [c, c .. ]]’

В чем проблема моя функция? Я не должен ничего менять в первой строке.

Ответы [ 5 ]

4 голосов
/ 04 марта 2020

Если цель состоит в том, чтобы получить бесконечный список из i s, тогда вы хотите repeat i.

Но если вам нужно только конечное число, учтите, что replicate n i - более короткий путь take n (repeat i)

Оба они будут работать без каких-либо ограничений на тип элементов списка - тогда как, как вы обнаружили, для обозначения «диапазон» требуется Enum.

3 голосов
/ 04 марта 2020

Данный код не компилируется, потому что аннотация типа не соответствует предполагаемому типу выражения.

Аннотация типа фактически необязательна, поэтому вы можете ее опустить. Если вы сделаете это, вы можете загрузить код в GHCi и спросить, что это за тип:

> :t constGrid
constGrid :: Enum a => a -> [[a]]

Это соответствует сообщению об ошибке, которое гласило:

Possible fix:
  add (Enum a) to the context of
    the type signature for:
      constGrid :: forall a. a -> [[a]]

Теперь сделайте это:

constGrid :: Enum a => a -> [[a]]
constGrid c = take 3 [take 3 [i,i ..] | i <- [c,c ..]]

Код теперь компилируется и работает как задумано:

> constGrid 'a'
["aaa","aaa","aaa"]
0 голосов
/ 04 марта 2020

Понятия не имею, как это исправить, но это исправленная версия.

constGrid :: a -> [[a]] 
constGrid c = take 3 [map (\x-> i) take 3 [1,1 .. 1] | map (\x-> c) [1,1 .. 1]]
0 голосов
/ 04 марта 2020

Играйте на клавиатуре.

-- movement 1. the theme.
take 1 [1,1 ..] == [1]
take 2 [1,1 ..] == [1,1]
take 3 [1,1 ..] == [1,1,1]

-- movement 2. development.
[1 | i <- [1]]  == [1]
[1 | i <- [1,1]]  == [1,1]
[1 | i <- [1,1,1]]  == [1,1,1]

-- movement 3. counterpoint.
take 1 [1,2 ..] == [1]
take 2 [1,2 ..] == [1,2]
take 3 [1,2 ..] == [1,2,3]

-- movement 4. coda.
[1 | i <- [1]]  == [1]
[1 | i <- [1,2]]  == [1,1]
[1 | i <- [1,2,3]]  == [1,1,1]

Er go,

[1 | i <- take n [1,2 ..]]  ==  [1, ....   -- or 'a' etc. instead of 1

[ [1 | i <- take n [1,2 ..]] 
  | i <- take n [1,2 ..] ]  ==  [[1, ....  -- or 'a' etc. instead of 1

Здесь счетная задача и выходная информация разделены. Проблема с вашей функцией заключалась в том, что вы использовали свой выходной элемент как для подсчета, так и для вывода. Но вы действительно должны считать только с Integer с.

take n [1,2 ..] также можно записать как [1,2..n] или просто [1..n].

0 голосов
/ 04 марта 2020

AFAICS список [i,i ..] не может быть собран, так как компилятор недостаточно знает о типе i. То есть он не может сделать вывод, что i является Enum, поэтому он не знает, как продолжить эту последовательность.

...