Haskell类型检查

时间:2011-12-19 18:46:26

标签: haskell typechecking

我正在尝试用Haskell做一些自学。

函数loadData从文件中读取一些数据,并根据整数参数对其进行一些处理以生成Map。我需要创建两个这样的映射并对其应用余弦相似度量。我试图首先找到两个映射的交集。但是,我遇到了类型错误(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 个答案:

答案 0 :(得分:4)

正如FUZxxl在对你的问题的评论中提到的,我质疑你对Haskell I / O的了解程度。这是克服使用该语言的最大障碍之一,似乎你想从更简单的任务开始。

但是,更确切地说,从字面上回答你的问题,这里有两种方式。首先,基本的,你需要先理解的那个是有意义的:

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作为其第一个参数的函数。

答案 1 :(得分:3)

这样的事情:

import Control.Applicative

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

请注意,其结果的类型为IO (Map.Map String Double)