Haskell:用IO字符串生成IO映射时键入错误
我有一个具有以下签名的函数:Haskell:用IO字符串生成IO映射时键入错误,haskell,io,monads,typing,Haskell,Io,Monads,Typing,我有一个具有以下签名的函数: Config -> IO (Map.Map String String) 它用于从配置中提取文件路径,然后加载该文件(包含文本行),然后将这些行解析为键和值——这就是为什么我需要将它们保存到map中的原因,最好是这样 因此,我创建了以下函数: let lns = liftM lines $ readFile $ getSet $ listF c in foldM (\m n -> liftM3 Map.insert n n m) (return
Config -> IO (Map.Map String String)
它用于从配置中提取文件路径,然后加载该文件(包含文本行),然后将这些行解析为键和值——这就是为什么我需要将它们保存到map中的原因,最好是这样
因此,我创建了以下函数:
let lns = liftM lines $ readFile $ getSet $ listF c in
foldM (\m n -> liftM3 Map.insert n n m) (return Map.empty) lns
现在,我希望Haskell意识到我希望这是一个字符串的IO映射(为简单起见,我现在不将行解析为键和VAL,而是将整行放在那里)
但是,我得到以下错误:
• Couldn't match type ‘Map.Map String’ with ‘IO’
Expected type: IO (Map.Map String String)
Actual type: Map.Map
String (Map.Map String (Map.Map String String))
• In the expression:
foldM (\ m n -> liftM3 Map.insert n n m) (return Map.empty) lns
In the expression:
let lns = liftM lines $ readFile $ getSet $ listF c
in foldM (\ m n -> liftM3 Map.insert n n m) (return Map.empty) lns
In an equation for ‘getEpisodeNames’:
getEpisodeNames c
| listF c == NotSet = return Map.empty
| otherwise
= let lns = liftM lines $ readFile $ getSet $ listF c
in foldM (\ m n -> liftM3 Map.insert n n m) (return Map.empty) lns
• Couldn't match type ‘[Char]’ with ‘Map.Map String String’
Expected type: Map.Map
String (Map.Map String (Map.Map String String))
Actual type: Map.Map String (Map.Map String String)
• In the expression: liftM3 Map.insert n n m
In the first argument of ‘foldM’, namely
‘(\ m n -> liftM3 Map.insert n n m)’
In the expression:
foldM (\ m n -> liftM3 Map.insert n n m) (return Map.empty) lns
• Couldn't match type ‘[]’ with ‘Map.Map String’
Expected type: IO (Map.Map String String)
Actual type: IO [String]
• In the third argument of ‘foldM’, namely ‘lns’
In the expression:
foldM (\ m n -> liftM3 Map.insert n n m) (return Map.empty) lns
In the expression:
let lns = liftM lines $ readFile $ getSet $ listF c
in foldM (\ m n -> liftM3 Map.insert n n m) (return Map.empty) lns
由此看来,似乎return Map.empty
试图用IO monad以外的东西来包装映射,这对我来说毫无意义
由于Haskell从不出错,我很清楚,我在某个地方搞砸了,我就是找不到,在哪里(尽管我很确定它在第二行,因为我已经使用ghci中的
:t
检查了lns的正确类型)。我还尝试将函数重写为>>=符号,而不是让。。。在…中,但没有帮助。谢谢您的帮助。好的,所以我已经成功地修复了代码,尽管我仍然不能完全确定问题出在哪里,所以如果有人能指出这一点,我将不胜感激
因此,与其
let lns = liftM lines $ readFile $ getSet $ listF c in
foldM (\m n -> liftM3 Map.insert n n m) (return Map.empty) lns
我曾经
(readFile . getSet $ listF c)
>>= (\tx -> return $ lines tx)
>>= (\lns -> return $ foldl (\m n -> Map.insert n n m) Map.empty lns)
好的,所以我实际上已经设法修复了代码,尽管我仍然不能完全确定问题出在哪里,所以如果有人能指出这一点,我将不胜感激 因此,与其
let lns = liftM lines $ readFile $ getSet $ listF c in
foldM (\m n -> liftM3 Map.insert n n m) (return Map.empty) lns
我曾经
(readFile . getSet $ listF c)
>>= (\tx -> return $ lines tx)
>>= (\lns -> return $ foldl (\m n -> Map.insert n n m) Map.empty lns)
foldM
的签名为
foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a
让我们看看你得到了什么:
return Map.empty :: IO (Map String String)
lns :: IO [String]
这显然与参数a
和[b]
不匹配。修复前者很容易:只需使用Map.empty
。对于后者,您需要访问lns
中的内容,这就是bind操作符的作用:
>>= :: m a -> (a -> m b) -> m b
因此
但由于您的操作是纯操作,所以您最好只使用fmap
和foldl
foldl (…) Map.empty <$> lns
foldl(…)Map.empty lns
foldM的签名是
foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a
让我们看看你得到了什么:
return Map.empty :: IO (Map String String)
lns :: IO [String]
这显然与参数a
和[b]
不匹配。修复前者很容易:只需使用Map.empty
。对于后者,您需要访问lns
中的内容,这就是bind操作符的作用:
>>= :: m a -> (a -> m b) -> m b
因此
但由于您的操作是纯操作,所以您最好只使用fmap
和foldl
foldl (…) Map.empty <$> lns
foldl(…)Map.empty lns
我想您使用的是let
而不是我没有使用do块,也没有使用>>=符号,我在这里放的片段实际上就是整个定义。另外,使用do表示法会产生完全相同的错误(另外,正如我所说,lns
变量实际上输入正确,foldM结果是错误的)。我认为您使用的是let
而不是,我没有使用do块,也没有使用>>=表示法,我放在这里的片段实际上是整个定义。另外,使用do表示法会产生完全相同的错误(另外,正如我所说,lns
变量实际上输入正确,foldM结果是错误的)。我认为您还不理解f(gx)
(这相当于让y=gx在fy
)和gx>=f
之间的区别。在IO中,后者运行IO操作gx
,获取其结果,并将其传递给f
,运行f
返回的操作。前者不运行gx
,但它将整个操作传递给f
,后者必须具有类型f::IO something->…
。在命令式语言中,它(非常粗略地)是f(()=>g(x))
(前者)和f(g(x))
(后者)之间的区别——前者不运行g(x)
。也许monad教程会有所帮助。我想你还不明白f(gx)
(这相当于let y=gx in fy
)和gx>=f
之间的区别。在IO中,后者运行IO操作gx
,获取其结果,并将其传递给f
,运行f
返回的操作。前者不运行gx
,但它将整个操作传递给f
,后者必须具有类型f::IO something->…
。在命令式语言中,它(非常粗略地)是f(()=>g(x))
(前者)和f(g(x))
(后者)之间的区别——前者不运行g(x)
。也许monad教程会有所帮助。