Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 编写简单的快速检查URL生成器时出现嵌套单子问题_Haskell_Uri_Monads_Quickcheck_Do Notation - Fatal编程技术网

Haskell 编写简单的快速检查URL生成器时出现嵌套单子问题

Haskell 编写简单的快速检查URL生成器时出现嵌套单子问题,haskell,uri,monads,quickcheck,do-notation,Haskell,Uri,Monads,Quickcheck,Do Notation,另一个新手问题可能是因为我没有掌握Haskell中的Monadicdo:我想使用modern URI包中的Text.URI类型为格式良好的URI编写一个简单的快速检查生成器。据我所知,这里涉及两种类型的monad:MonadThrow用于URI构造时的错误处理,以及来自QuickCheck的Gen 下面是我实现生成器的尝试。它不进行类型检查: import qualified Text.URI as URI uriGen :: Gen URI.URI uriGen = do sc &l

另一个新手问题可能是因为我没有掌握Haskell中的Monadic
do
:我想使用
modern URI
包中的
Text.URI
类型为格式良好的URI编写一个简单的快速检查生成器。据我所知,这里涉及两种类型的monad:
MonadThrow
用于URI构造时的错误处理,以及来自QuickCheck的
Gen

下面是我实现生成器的尝试。它不进行类型检查:

import qualified Text.URI as URI

uriGen :: Gen URI.URI
uriGen = do
    sc <- elements ["https", "http", "ftps", "ftp"]
    tld <- elements [".com", ".org", ".edu"]
    hostName <- nonEmptySafeTextGen -- (:: Gen Text), a simple generator for printable text. 
    uri <- do
        scheme <- URI.mkScheme sc
        host <- URI.mkHost $ (hostName <> "." <> tld)
        return $ URI.URI (Just scheme) (Right (URI.Authority Nothing host Nothing)) Nothing [] Nothing
    return uri
从这个错误中,我怀疑我关于打开和包装URI片段的直觉是错误的。我哪里会犯错?什么是正确的直觉


非常感谢你的帮助

最简单的解决方案是将单子相互嵌套,例如:

——MonadThrow的一个实例是Maybe,因此这是一个可能的类型签名
--uriGen::Gen(可能是URI.URI)
uriGen::MonadThrow m=>Gen(muri.URI)
尿素=do
sc Gen b
与上面的类型匹配:
uriGen::Gen(可能是URI.URI)


编辑:在评论中回答您的问题:

MonadThrow
是一个类型类,它是
Monad
的超类(请参阅)。你写的相当于


uriGen::Gen URI.URI
尿素=do

sc也许您可以使用
这样的映射
MonadThrow
实例来描述
也许
一个重要的细节:您希望程序在失败时做什么?它应该重试直到您得到一个有效的URI,还是应该返回一个指示失败的值?非常感谢您的帮助。我的理解是:除了故障时该怎么办这个问题之外,我的类型错误是因为我使用了
url
的一元绑定,而不是
let
绑定?因为外部单子是
Gen
而不是
MonadThrow
,所以单子绑定不会进行类型检查?@UlrichSchuster我现在更新了我的答案。这说明了吗?是的,你基本上是对的。唯一的细节是,
MonadThrow
不仅仅是一个
Monad
,而是一类Monad,其中包括
可能
或者
或者
IO
,但不是
Gen
@UlrichSchuster如果你看看
如何做
-符号desugars,它可能会帮助你直觉地了解为什么它是等价的:
    • No instance for (MonadThrow Gen)
        arising from a use of ‘URI.mkScheme’
    • In a stmt of a 'do' block: scheme <- URI.mkScheme sc
      In a stmt of a 'do' block:
        uri <- do scheme <- URI.mkScheme sc
                  host <- URI.mkHost $ (hostName <> "." <> tld)
                  return
                    $ URI.URI
                        (Just scheme)
                        (Right (URI.Authority Nothing host Nothing))
                        Nothing
                        []
                        Nothing
Prelude Test.QuickCheck> :i Gen
newtype Gen a
  = Test.QuickCheck.Gen.MkGen {Test.QuickCheck.Gen.unGen :: Test.QuickCheck.Random.QCGen
                                                            -> Int -> a}
    -- Defined in ‘Test.QuickCheck.Gen’
instance [safe] Applicative Gen -- Defined in ‘Test.QuickCheck.Gen’
instance [safe] Functor Gen -- Defined in ‘Test.QuickCheck.Gen’
instance [safe] Monad Gen -- Defined in ‘Test.QuickCheck.Gen’
instance [safe] Testable prop => Testable (Gen prop)
  -- Defined in ‘Test.QuickCheck.Property’