我正在尝试用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
答案 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)
。