Как применить функцию к списку векторов? - PullRequest
2 голосов
/ 25 марта 2012

У меня большой вложенный вектор, который выглядит следующим образом:

import Data.Vector
let x = fromList [["a", "b", "12", "d"], ["e", "f", "34", "g"]...]

Я хотел бы преобразовать строки в целые числа в позиции 2 в каждом вложенном списке, который я пытался сделать с помощью карты и пониманиякак это:

let y = Data.Vector.map (\a -> read a :: Int) [i !! 2 | i <- x]

Что я делаю не так?Я хотел бы вывод:

(("a", "b", 12, "d"), ("e", "f", 34, "g")...)

Ответы [ 2 ]

8 голосов
/ 25 марта 2012

Здесь есть ряд проблем.

Прежде всего, результатом понимания списка является список, поэтому вы вызываете Data.Vector.map для списка, который не будет работать. И x внутри понимания - это Vector, что является еще одним несоответствием типов. Либо используйте список вместо вектора (вместе с Prelude.map), либо преобразуйте список в Vector (в этом случае вы не можете использовать понимание списка).

Во-вторых, игнорируя проблему списка / Vector, [i !! 2 | i <- x] даст вам список, содержащий только элементы в позиции 2 из каждого подсписка. Используя ваш пример, понимание даст ["12", "34"]. Затем, когда вы отобразите read поверх него, вы получите [12, 34], а не результат, для которого вы стреляете.

Наконец, вывод, который вы хотите увидеть, недопустим для списков или для Vectors в Haskell. Контейнеры обоих типов должны быть однородными, то есть они не могут содержать значения более одного типа. [Int] не может содержать String с, а [String] не может содержать Int с, но ваш желаемый вывод содержит оба. Существуют способы обойти это, используя экзистенциальные типы, но есть вероятность, что есть лучшее решение для вашей основной проблемы, чем пытаться создавать гетерогенные коллекции.

Редактировать: Вы отредактировали последнюю часть своего поста, чтобы использовать кортежи, поэтому приведенный выше абзац больше не применяется. Первые две упомянутые проблемы все еще существуют.

Если вы начнете со списка из 4-х кортежей ([(String, String, String, String)]), вы можете получить то, что хотите, вот так:

> let x = [("a", "b", "12", "d"), ("e", "f", "34", "g")]
> map (\(a, b, c, d) -> (a, b, read c :: Int, d)) x
[("a", "b", 12, "d"), ("e", "f", 34, "g")]
1 голос
/ 25 марта 2012

Похоже, вы должны использовать более сложный тип данных, чем 4-кортежный, например

data YourType_StringNum = YourType_StringNum { ytsnLetters1 :: String
                                             , ytsnLetters2 :: String
                                             , ytsnNumber :: String
                                             , ytsnLetters3 :: String }
data YourType_IntNum = YourType_IntNum { ytinLetters1 :: String
                                       , ytinLetters2 :: String
                                       , ytinNumber :: Int
                                       , ytinLetters3 :: String }

(конечно, с лучшими идентификаторами).Затем определите функцию, подобную

toYtin :: YourType_StringNum -> YourType_IntNum
toYtin(YourType_StringNum a b s c) = YourType_IntNum a b (read s) c

. Таким образом, ваша проблема сводится к преобразованию Vector YourType_StringNum в Vector YourType_IntNum, и это тривиально делается с помощью Data.Vector.map toYtin.

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