Haskell-在列表Monad中需要[Char]时获取Char类型

Haskell-在列表Monad中需要[Char]时获取Char类型,haskell,io,monads,Haskell,Io,Monads,我正在练习Haskell,尝试制作一个程序,查找.mp3和.flac元数据并将其整齐地写入文件。我一个人走了这么远,但我对我应该做什么感到很困惑。下面是代码的主要部分: builddir xs = do writeto <- lastest getArgs let folderl b = searchable <$> (getPermissions b) let filel c = ((lastlookup mlookup c) &&

我正在练习Haskell,尝试制作一个程序,查找.mp3和.flac元数据并将其整齐地写入文件。我一个人走了这么远,但我对我应该做什么感到很困惑。下面是代码的主要部分:

builddir xs = do
    writeto  <- lastest getArgs
    let folderl b = searchable <$> (getPermissions b)
    let filel   c = ((lastlookup mlookup c) &&) <$> ((not <$> folderl c))
    a <- listDirectory xs
    listdirs <- filterM (folderl) (map ((xs ++ "/") ++) a)
    filedirs <- filterM (filel)   (map ((xs ++ "/") ++) a)
    let tagfiles = mapM (tagsort) filedirs
    putStrLn $ concat listdirs
    putStrLn $ concat tagfiles


tagsort xs = do
    nsartist <- getTags xs artistGetter
    nsalbum  <- getTags xs albumGetter
    artist   <- init $ drop 8 $ show nsalbum
    album    <- init $ drop 7 $ show nsalbum
    (artist ++ " - " ++ album)
我知道,这很乱。在ghci中运行时,我得到以下信息:

• Couldn't match expected type ‘[Char]’ with actual type ‘Char’
• In the first argument of ‘(++)’, namely ‘artist’
  In a stmt of a 'do' block: artist ++ " - " ++ album
  In the expression:
    do nsartist <- getTags xs artistGetter
       nsalbum <- getTags xs albumGetter
       artist <- init $ drop 8 $ show nsalbum
       album <- init $ drop 7 $ show nsalbum
       ....
       60    artist ++ " - " ++ album
我很难理解为什么会这样。在我的测试程序中运行类似命令:

main = do
artg <- getTags "/home/spilskinanke/backlogtest/02 - await rescue.mp3" artistGetter
let test = init $ drop 8 $ show artg
print test
这个很好用。在ghci中将字符串65daysofstatic打印到我的终端。它显然不是字符类型。那么为什么在我的代码中被称为Char呢? 还要注意,在添加引用元数据模块的任何代码之前,我正在使用htaglib,该程序在测试中运行良好。由于没有tagfiles函数和tagsort monad,我可以为某个目录设置一个arg,我的测试将成功打印一个包含所有可读文件夹的文件路径列表,以及另一个包含所有文件的文件路径列表,这些文件的结尾是我在mlookup中想要的,在本例中是.mp3、.mp4、.flac和.wav。任何帮助都将不胜感激。

您在tagsort中混淆了IO和[]:


一般来说,每个do块必须在单个monad中,直到您开始学习如何使用monad transformers来组合不同的效果。因此,在IO块中,绑定语句右侧的任何内容都必须是IO操作;如果你只想做纯计算,你可以使用let或者仅仅是内联表达式,如果你不需要绑定某个名字的话。最后,do块中的最后一条语句也必须是特定monad中的一个操作。这通常是一个纯值,仅用pure::Applicative f=>a->f a或return::monad m=>a->m a包装在monad中,它做同样的事情,但由于更严格的Monad约束,在更少的上下文中工作。

谢谢您的快速响应Jon!我想是时候休息一下了,因为现在我可以清楚地看到,在我运行的测试程序中,我实际上使用了let绑定,而在我的主要代码块中没有使用。不知道我怎么会错过!如果我有另一个与此非常相关的问题,我应该创建一个全新的线程还是在这里简单地提问?@Sagarmatha新问题应该是新问题。如果给每个顶级定义一个类型签名,您将得到更好的错误消息,并写出更好的问题。另外,当您只给出一段代码时,请确保1。显示您的导入和2。给出您编写的在片段中调用/使用但未在片段中定义的所有函数/值的类型签名。
tagsort xs = do

    -- Okay, run IO action and bind result to ‘nsartist’
    nsartist <- getTags xs artistGetter

    -- Similarly for ‘nsalbum’
    nsalbum  <- getTags xs albumGetter

    -- Mistaken: ‘init …’ returns a list, not an ‘IO’ action
    artist   <- init $ drop 8 $ show nsalbum
    album    <- init $ drop 7 $ show nsalbum

    -- You are also missing a ‘pure’ or ‘return’ here
    (artist ++ " - " ++ album)
tagsort xs = do
    nsartist <- getTags xs artistGetter
    nsalbum  <- getTags xs albumGetter
    let artist = init $ drop 8 $ show nsalbum
    let album = init $ drop 7 $ show nsalbum
    pure (artist ++ " - " ++ album)