Haskell-在List Monad中期望[Char]时获取Char类型

Sag*_*tha -1 io monads haskell

我正在通过尝试创建一个查找.mp3和.flac元数据并将其整齐地写入文件的程序来练习Haskell。我已经走了这么远,但是我对应该做的事情感到很沮丧。这是这里的主要代码块:

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)
Run Code Online (Sandbox Code Playgroud)

我知道,这很混乱。在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
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么会这样。在我的测试程序中运行类似的命令:

main = do
artg <- getTags "/home/spilskinanke/backlogtest/02 - await rescue.mp3" artistGetter
let test = init $ drop 8 $ show artg
print test
Run Code Online (Sandbox Code Playgroud)

这工作得很好。在我的ghci终端中输出字符串“ 65daysofstatic”。显然不是Char类型。那么为什么在我的代码中被称为Char?还要注意,在添加任何引用我正在使用的元数据模块的代码段(htaglib)之前,该程序在测试中运行良好。有了tagfiles函数和tagort monad,我可以为某个目录设置一个arg,并且我的测试将成功打印一个包含所有可读文件夹的FilePath列表,以及另一个包含所有以我想要的结尾的文件的FilePaths列表。 mlookup,在这种情况下为.mp3,.mp4,.flac和.wav。任何帮助,将不胜感激。

Jon*_*rdy 6

您正在混音,IO并且[]tagsort

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)
Run Code Online (Sandbox Code Playgroud)

该修补程序是简单的:用一个let语句而不是一个绑定声明<-,并添加pure作出IO String了的String您有:

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)
Run Code Online (Sandbox Code Playgroud)

一般来说,每个do块都必须位于一个monad中,直到您开始学习使用monad转换器组合不同的效果为止。因此,在一个IO块中,绑定语句右边的任何内容都必须是一个IO动作;如果您只想进行纯计算,则可以使用let(或者如果不需要将某些内容绑定到名称,则可以使用内联表达式)。最后,do块中的最后一条语句也必须是特定monad中的一个动作-这通常是一个纯值,只是用pure :: Applicative f => a -> f a(或包裹在monad中return :: Monad m => a -> m a,它具有相同的作用,但在更多情况下可以使用,因为限制性Monad约束)。