Haskell 使ReadArgs 1.0与单个参数一起工作
玩弄于此,它似乎不支持单参数情况Haskell 使ReadArgs 1.0与单个参数一起工作,haskell,command-line-arguments,Haskell,Command Line Arguments,玩弄于此,它似乎不支持单参数情况 {-# LANGUAGE ScopedTypeVariables #-} import ReadArgs (readArgs) main = do (foo :: Int) <- readArgs print foo 我的问题有两个: readArgs是如何工作的 如何调整该库,使其也可以使用单个参数 注意:ReadArgs的1.1版消除了这个“错误”;请参阅注释。我不太了解启用所需的所有扩展,但您可以定义ReadArgs.ArgumentT
{-# LANGUAGE ScopedTypeVariables #-}
import ReadArgs (readArgs)
main = do
(foo :: Int) <- readArgs
print foo
我的问题有两个:
readArgs
是如何工作的注意:ReadArgs的1.1版消除了这个“错误”;请参阅注释。我不太了解启用所需的所有扩展,但您可以定义
ReadArgs.ArgumentTuple a
的一个实例(尽管它实际上不是一个语义正确的名称),如下所示:
{-# LANGUAGE FlexibleInstances, UndecidableInstances,
OverlappingInstances, ScopedTypeVariables #-}
import ReadArgs
instance (Argument a) => ArgumentTuple a where
parseArgsFrom ss = do
a :& () <- parseArgsFrom ss
return a
usageFor a = usageFor (a :& ())
main = do
(foo :: Int) <- readArgs
print foo
{-#语言灵活实例,不可判定实例,
重叠实例,范围类型变量#-}
导入ReadArgs
实例(参数a)=>参数元组a,其中
parseArgsFrom ss=do
答:&()据我所知,该包使用元组来模拟类型安全的异构列表。正如您所注意到的,当您只需要一个参数时,这会导致问题,因为Haskell中没有一个元组
但是,该包还为异构列表提供了一个合适的类型,可以用它代替元组::&
类型。使用它类似于:
运算符,将空元组()
用作终止符:
(foo :: Int) :& (bar :: String) :& () <- readArgs
(foo::Int):&(bar::String):&()一个延迟解决方案是滥用“可选参数”功能:
并稍微扭曲了使用信息:
$ runhaskell args.hs 3 foo
usage: args.hs Int [()]
但它确实拒绝了不是()
的额外参数,并且它确实可以按需要工作:
$ runhaskell args.hs 3
3
另一个答案,只是为了好玩:具体化Daniel Wagner关于为OneTuple
添加一个实例的建议:
{-# LANGUAGE ScopedTypeVariables #-}
import ReadArgs
import Data.Tuple.OneTuple
instance (Argument a) => ArgumentTuple (OneTuple a) where
parseArgsFrom ss = do
a :& () <- parseArgsFrom ss
return $ OneTuple a
usageFor (OneTuple a) = usageFor (a :& ())
main = do
OneTuple (foo :: Int) <- readArgs
print foo
{-#语言范围的TypeVariables}
导入ReadArgs
导入Data.Tuple.OneTuple
实例(参数a)=>参数元组(一元组a),其中
parseArgsFrom ss=do
答:&()听起来readArgs希望提供一个元组。我认为一个项目的元组不可能是一个——(1)只是1
——所以这可能就是问题所在。@TikhonJelvis是的,这确实是问题所在。但我仍然想知道它是如何工作的,以及如何调整它以适应非元组的情况。可能正确的解决方案是为s编写一个实例。您想知道它是如何工作的吗?@rampion anything and everything.:)hammar的解释让我很满意,但也欢迎更深入的解释。尽管为OneTuples定义一个实例是有意义的。我也应该注意到这一点,因为我在回答中定义了一个实例:a:&(),这不是最干净的解决方案,但我必须承认,我几乎立刻就想到了与之非常相似的东西。TypeSynonymInstances
和TypeOperators
对于您的代码片段不是必需的,尽管它们在ReadArgs中使用。我已经更新了我的示例。。。谢谢正如你可能注意到的那样,这就是我得到它们的原因。我接受这个答案,因为它提供了我所要求的确切语法。:)我想在某种程度上,我曾经尝试过类似的方法,但遇到了重叠实例的问题,但您似乎已经证明了它是有效的。如果您给我发了一封邮件,我很乐意将其集成到下一个软件包版本中。@DanBurton:merged,packaged,and+1,用于去除语言pragmas。除此之外,使用OneTuple
还有很好的语义原因吗?我不确定我对这件事有什么看法,我只是好奇。为什么需要ScopedTypeVariables
pragma?@is7sdoonetuple(foo::Int)>=(\(OneTuple(foo::Int))->…)
,这显然需要ScopedTypeVariables
来进行类型注释。我不知道为什么,但如果我不把它放进去,GHC会对我大喊大叫,并建议“使用-XScopedTypeVariables”@Dan谢谢。显然,在模式匹配时,任何类型声明都需要pragma。例如在[1,2]>=\(x::Int)->[x+1]
中。
(foo :: Int, _ :: Maybe ()) <- readArgs
$ runhaskell args.hs 3 ()
3
$ runhaskell args.hs 3 foo
usage: args.hs Int [()]
$ runhaskell args.hs 3
3
{-# LANGUAGE ScopedTypeVariables #-}
import ReadArgs
import Data.Tuple.OneTuple
instance (Argument a) => ArgumentTuple (OneTuple a) where
parseArgsFrom ss = do
a :& () <- parseArgsFrom ss
return $ OneTuple a
usageFor (OneTuple a) = usageFor (a :& ())
main = do
OneTuple (foo :: Int) <- readArgs
print foo