似乎无法实现正确要么
好吧所以这里是我当前的代码:似乎无法实现正确要么
import System.IO
import System.Environment
import System.Directory
main = do
unfiltered <- getArgs ; home <- getHomeDirectory ; let db = home ++ "/.grindstone"
case unfiltered of
(x:xs) -> return()
_ -> error "No command given. See --help for more info."
command:args <- getArgs
createDirectoryIfMissing True db
let check = case args of
[] -> error "No arguments given. See --help for more info."
_ -> do let ([email protected](param:_),rest) = span (\(c:_) -> c=='-') args
if length params > 1 then error ("No arguments given for " ++ param)
else do
let (pArgs,_) = span (\(c:_) -> c/='-') rest
return (param, pArgs) :: Either (IO()) (String, [String])
let add = print "sup"
let cmds = [("add", add)]
let action = lookup command cmds
case action of
Nothing -> error "Unknown command."
(Just action) -> action
的主要问题是与检查。我试图实现任何一种类型,因为我希望它不是出错,或其他功能使用返回的东西,但是,它目前示数出有:
grindstone.hs:21:23:
No instance for (Monad (Either (IO())))
arising from a use of `return' at grindstone.hs:21:23-43
Possible fix:
add an instance declaration for (Monad (Either (IO())))
In the expression:
return (param, pArgs) :: Either (IO()) (String, [String])
In the expression:
do { let (pArgs, _) = span (\ (c : _) -> ...) rest;
return (param, pArgs) :: Either (IO()) (String, [String]) }
In the expression:
if length params > 1 then
error ("No arguments given for " ++ param)
else
do { let (pArgs, _) = ...;
return (param, pArgs) :: Either (IO()) (String, [String]) }
我只在Haskell和避风港开始了”对于monads来说,处理得太多了,所以我想我会在这里问。有人有主意吗?
导致编译问题的错误是,如果表达式不是Either
值,则直接将表达式转换为Either (IO()) (String, [String])
类型。 (编译器不会输出非常有用的错误消息。)
要创建一个Either值[1],我们使用数据构造函数Left
和Right
。约定(从库页面)是错误是一个左值,而正确的值是一个正确的值。
我做你的ARG检查功能的快速改写为
checkArgs :: [String] -> Either String (String, [String])
checkArgs args =
case args of
[] -> Left "No arguments given. See --help for more info."
_ -> let ([email protected](param:_),rest) = span (\(c:_) -> c=='-') args in
if length params > 1 then
Left ("No arguments given for " ++ param)
else
let (pArgs,_) = span (\(c:_) -> c/='-') rest in
Right (param, pArgs)
注意,ARG检查功能不与任何外部IO()
库函数交互等方面具有纯功能型。一般来说,如果您的代码没有一元元素(IO()
),则可以更纯粹地将其编写为纯功能样式。 (当在Haskell中开始时,这绝对是我会推荐的,而不是试图让你的头立即在monads/monad变形金刚/等等。)
当你对单子更舒适时,你可能想要退房Control.Monad.Error
[2],其可以将与Either
类似的功能作为单元包装,并且将封装一些细节,如始终为计算错误的Left
。
[1] http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/Data-Either.html
[2] http://hackage.haskell.org/packages/archive/mtl/1.1.0.2/doc/html/Control-Monad-Error.html
Either (IO()) (String, [String])
是包含一个IO动作或 (String, [String])
,所以这种类型的值可以是Left IO()
或 Right (String, [String])
一个类型。 Left
值通常表示Haskell中发生的错误 。这个错误可以用你想要的任何类型表示,例如 ,错误代码(Int
)或者说String
表示发生了什么。 如果您使用IO()
作为表示错误的类型,那么您将无法通过 来提取有关该错误的任何信息。您稍后可以执行IO操作。
您要找的型号不是Either (IO()) (String, [String])
, 是Either String (String, [String])
。使用此类型可以获取有关 错误(String
)的信息。现在,你不需要任何IO操作成Either
类型,所以你 可以删除所有do
表达式:
let check = case args of
[] -> Left "No arguments given. See --help for more info."
_ -> let ([email protected](param:_),rest) = span (\(c:_) -> c=='-') args
in if length params > 1
then Left ("No arguments given for " ++ param)
else let (pArgs,_) = span (\(c:_) -> c/='-') rest
in Right (param, pArgs)
我会使用'when'函数编写代码如下:http://paste.ubuntuusers.de/399917/。这种风格更容易阅读,并减少了“正确行走”代码的数量。 – fuz 2011-02-24 18:37:47
HM ..谢谢。显然,当我在纯函数形式中定义checkArgs而不是在main中使用'Either(IO())(String,String)工作正常:P - http://paste.pocoo.org/show/344101/ – 2011-02-24 22:16:42