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?@is7s
    doonetuple(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