Проверка типа Haskell - PullRequest
       5

Проверка типа Haskell

1 голос
/ 19 декабря 2011

Я пытаюсь сделать самообучение с Haskell.

Функция loadData считывает некоторые данные из файла и, основываясь на целочисленном параметре, выполняет некоторую обработку для его создания карты.Мне нужно создать две такие карты и применить к ним показатель косинусного сходства. Сначала я пытаюсь найти пересечение двух карт.Тем не менее, я сталкиваюсь с ошибкой типа (Couldn't match expected type `a0 -> Map.Map k0 a1' with actual type `IO (Map.Map [Char] Double)') Как я могу передать вывод loadData в Map.intersection.Нужен ли мне аппликатор функции $?

loadData :: Int -> FilePath -> IO (Map.Map [Char] Double)

Map.intersection :: Ord k => Map.Map k a -> Map.Map k b -> Map.Map k a

Ответы [ 2 ]

4 голосов
/ 19 декабря 2011

Как FUZxxl упомянул в комментарии к вашему вопросу, я спрашиваю, насколько вы изучили ввод / вывод Haskell.Это одно из главных начальных препятствий для использования языка, и кажется, что вы хотели бы начать с более простых задач.

Но, тем не менее, чтобы ответить на ваш вопрос более буквально, вот двапути.Во-первых, элементарный, тот, который вам нужно понять в первую очередь, прежде чем остальные приобретут смысл:

processData :: Int -> FilePath -> Int -> FilePath -> IO (Map.Map [Char] Double)
processData int1 path1 int2 path2 =
    do map1 <- loadData int1 path1
       map2 <- loadData int2 path2
       return (Map.intersection map1 map2)

Существуют более сложные ответы, которые включают абстрагирование шаблона, показанного выше, в функцию.Более простой способ сделать это - использовать функцию liftM2 из модуля Control.Monad.Я приведу пример реализации liftM2 только для того, чтобы было очевидно, как она связана с кодом выше:

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 f mx my = do x <- mx
                    y <- my
                    return (f x y)

С liftM2 мы можем переписать processData следующим образом:

processData :: Int -> FilePath -> Int -> FilePath -> IO (Map.Map [Char] Double)
processData int1 path1 int2 path2 =
    liftM2 Map.intersection (loadData int1 path1) (loadData int2 path2)

Ответ dave4420 немного сложнее;к чему сводится то, что Control.Applicative имеет два оператора (<$> и <*>), которые в комбинации могут делать то же самое, что и liftM2, но для произвольного числа аргументов для функции, которую liftM2 принимает в качестве своегоПервый аргумент.

3 голосов
/ 19 декабря 2011

Примерно так:

import Control.Applicative

Map.intersection <$> loadData param filename1 <*> loadData param filename2

Обратите внимание, что результат имеет тип IO (Map.Map String Double).

...