Проблемы реализации функции карты Haskell - PullRequest
2 голосов
/ 27 апреля 2011

Я только начал изучать Haskell, и у меня возникли проблемы с адаптацией к языку, например, в отношении реализации map более конкретно при попытке выполнить операции, аналогичные приведенным ниже;

rotate :: Dimensions ->  imgBlock -> [(imgBlock,Int)]
rotate d ((p, pix), s, t) 
  = zip [((p, f pix), s, t) | f <- transformate (fst d)] [0..7]

makeAllRotations :: Dimensions -> [imgBlock] -> [(imgBlock,Int)]
makeAllRotations d ib = map concat (rotate d ib)              //Error points Here

Где

type imgBlock = (Block, Int, Int)
type Block = (Pnt, Pxl)
type Dimensions = (Int, Int)

И это одна из ошибок, которые я получаю

asdf.hs:73:30:
    Couldn't match expected type `(imgBlock, Int)'
                with actual type `[a0]'
    Expected type: [[a0]] -> (imgBlock, Int)
      Actual type: [[a0]] -> [a0]
    In the first argument of `map', namely `concat'
    In the expression: map concat (rotate d ib)

Я чувствую себя довольно разочарованным, пытаясь приспособиться к этой новой программной «парадигме», где большинство вещей, которые яудалось сделать путем проб и ошибок.Я, очевидно, не правильно понимаю map, хотя я прочитал документацию на этом сайте , но все примеры показаны в консоли, как map (2+) [1,2,3], не так часто при использовании их в функциях.

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

1 Ответ

4 голосов
/ 27 апреля 2011

Лучший способ найти проблему - взглянуть на типы:

rotate :: Dimensions -> ImgBlock -> [(ImgBlock,Int)]
makeAllRotations :: Dimensions -> [ImgBlock] -> [(ImgBlock,Int)]
map :: (a -> b) -> [a] -> [b]
concat :: [[a]] -> [a]

Функция map пытается вызвать concat для каждой из пар (ImgBlock, Int) в списке, возвращаемом функцией rotate. Но concat ожидает получить вложенный список в качестве аргумента. Но большая вещь, которая помогла мне понять, как это исправить, была rotate d ib. Второй аргумент для поворота - ImgBlock, но в этом контексте ib :: [ImgBlock]. Вы не можете передать список, когда ожидается один элемент. Но это то, для чего предназначена функция карты. Это позволяет вам взять функцию, которая принимает один элемент («a» в сигнатуре типа выше) и использовать эту функцию, когда у вас есть [a]. Я подозреваю, что вы хотите что-то вроде этого:

makeAllRotations d ib = concat $ map (rotate d) ib

Поскольку rotate возвращает список, map (rotate d) ib возвращает список списков, который идеально подходит в качестве первого аргумента функции concat.

...