Haskell 中的奇怪返回
checkstring :: [String] -> Int -> [String]
checkstring p n = do z <- doesFileExist (p !! n)
if z
then p
else error $ "'" ++ (p !! n) ++ "' file path does not exist"
它通过查看“n”来检查字符串中的元素(因此,如果 n = 2,它将检查列表中的第二个字符串),然后查看它是否存在。如果存在则返回原始字符串列表,如果不存在则出错。为什么要这样做呢? :
Couldn't match expected type `[t0]' with actual type `IO Bool'
In the return type of a call of `doesFileExist'
In a stmt of a 'do' expression: z <- doesFileExist (p !! n)
checkstring :: [String] -> Int -> [String]
checkstring p n = do z <- doesFileExist (p !! n)
if z
then p
else error $ "'" ++ (p !! n) ++ "' file path does not exist"
It checks for a element in the string by looking at "n"(so if n = 2 it will check if the second string in the list) then see if it exists. If it does exist it will return the original string list, if not it will error.Why does it do this? :
Couldn't match expected type `[t0]' with actual type `IO Bool'
In the return type of a call of `doesFileExist'
In a stmt of a 'do' expression: z <- doesFileExist (p !! n)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
doesFileExist
的类型是String -> IO布尔
。如果你的程序想要知道一个文件是否存在,它必须与文件系统交互,这是一个 IO 操作。如果您希望checkString
函数执行此操作,它还必须具有某种基于 IO 的类型。例如,我认为这样的事情会起作用,尽管我还没有尝试过:The type of
doesFileExist
isString -> IO Bool
. If your program wants to know whether a file exists, it has to interact with the file system, which is an IO action. If you want yourcheckString
function to do that, it will also have to have some kind of IO-based type. For example, I think something like this would work, though I haven't tried it:对 MatrixFrog 在他的回答中提到的内容进行补充。如果您查看函数签名,即
[String] ->整数-> [String]
它表明该函数是一个纯函数,不涉及任何副作用,在函数体中,您使用的是doesFileExist
,其签名为字符串 -> IO Bool
其中 IO 的存在表明它是一个不纯的函数,即它涉及一些 IO。在haskell中,不纯函数和纯函数之间有严格的分离,事实上,如果你的函数调用了比你的函数不纯的其他函数,那么它也是不纯的。因此,在您的情况下,您的函数checkString
需要是不纯的,这可以通过使其返回IO [String]
来完成,这就是 MatrixFrog 在他的答案中提到的。另一方面,我建议您可以使该函数类似于:
checkString :: 字符串 -> IO (Maybe String)
,因为您的函数不需要整个字符串列表,因为它只需要列表中的特定字符串来完成其工作,而不是抛出错误,您可以使用 Maybe 来检测错误。这只是一个建议,但这还取决于您的函数的使用方式。
To add to what MatrixFrog has mentioned in his answer. If you look at your function signature i.e
[String] -> Int -> [String]
it indicates that this function is a pure function and doesn't involved any side effects, where as in your function body you are usingdoesFileExist
which has a signature ofString -> IO Bool
where the presence of IO indicates it is a impure function i.e it involves some IO. In haskell there is a strict separation between impure and pure functions and as a matter of fact if your function calls some other function which is impure than your function is also impure. So in your case your functioncheckString
needs to be impure and that can be done by making it returnIO [String]
, which is what MatrixFrog has mentioned in his answer.On another note, I would suggest that you can make the function to be something like:
checkString :: String -> IO (Maybe String)
,as your function doesn't need the whole list of string as it just need a specific string from the list to do its work and rather than throwing an error you can use Maybe to detect the error.This is just a suggestion but it also depends on how your function is being used.
我认为问题是你的类型签名强制 do 块假设它是其他一些 monad。例如,假设您正在列表 monad 中工作。然后,您可以编写
在列表 monad 的情况下,
return
只是返回单例列表,因此您会得到类似的行为(我个人的观点是,如果 GHC 有一个打印出可能导致类型错误的常见错误的选项;我对提问者表示同情,因为我收到了很多需要时间才能弄清楚的类型错误消息)。
I think the problem is that your type signature forces the
do
block to assume that it is some other monad. For example, suppose you're working in the list monad. Then, you could writeIn the case of the list monad, the
return
simply returns the singleton list, so you get behavior like,(My personal opinion is that it would be very helpful if the GHC had an option to print out common mistakes that could cause a type error; I sympathize with the asker in that I've gotten a lot of type error messages that take time to figure out).