Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell:用IO字符串生成IO映射时键入错误_Haskell_Io_Monads_Typing - Fatal编程技术网

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教程会有所帮助。