无法匹配类型 也许与否 也许在网络上.URI



假设我想解析一个环境变量,如果没有它,则默认为localhost,使用https://hackage.haskell.org/package/network-2.3/docs/Network-URI.html

我可以写这样的函数:

parseRabbitURI :: Text -> Maybe URI.URI
parseRabbitURI "" = URI.parseURI "amqp://guest:guest@127.0.0.1/"
parseRabbitURI uri = (URI.parseURI . toS) uri

这很好用。现在让我们假设我想处理错误。我注意到parseURI返回一个Maybe,所以表面上我只需要对此进行模式匹配。所以我创建了一个自定义错误:

data CustomError = MyCustomError Text deriving(Show)

我创建了一个助手函数:

parsedExtractor
:: MonadError CustomError.MyCustomError m
=> Text
-> Maybe URI.URI
-> m(URI.URI)
parsedExtractor originalString Nothing = throwError $ FlockErrors.FailedToParseURI originalString
parsedExtractor _ (Just uri) = do
pure uri

最后,我修改了我的初始函数:

parseRabbitURI :: MonadError CustomError.MyCustomError m => Text -> m(URI.URI)
parseRabbitURI "" = URI.parseURI "amqp://guest:guest@127.0.0.1/" >>= parsedExtractor "amqp://guest:guest@127.0.0.1/"
parseRabbitURI uri = (URI.parseURI . toS) uri >>= parsedExtractor uri

这无法使用进行编译

• Couldn't match type ‘URI.URI’ with ‘Maybe URI.URI’
Expected type: URI.URI -> Maybe URI.URI
Actual type: Maybe URI.URI -> Maybe URI.URI
• In the second argument of ‘(>>=)’, namely ‘parsedExtractor uri’
In the expression: (URI.parseURI . toS) uri >>= parsedExtractor uri
In an equation for ‘parseRabbitURI’:
parseRabbitURI uri
= (URI.parseURI . toS) uri >>= parsedExtractor uri

|23|parseRabbitURI uri=(uri.parseURI.toS(uri>>=parsedExtractor uri|

我一辈子都不明白为什么。如果最初的实现返回一个Maybe,为什么它会转换为一个我无法传递的展开器URI.URI?

至关重要的是,当我更改parsedExtractor上的模式以期望字符串时,它无法使用反向消息(

Couldn't match expected type ‘URI.URI’
with actual type ‘Maybe URI.URI’

我觉得我一定错过了一些根本的东西。这是怎么回事?

我一辈子都不明白为什么。如果初始实现返回一个Maybe,为什么它转换为展开器然后我不能通过的URI.URI?

参考Control.Monad中>>=的定义,它具有类型签名:

(>>=) :: m a -> (a -> m b) -> m b

现在,与表达式进行比较:

(URI.parseURI . toS) uri >>= parsedExtractor uri

我们有:

m a        ~ (URI.parseURI . toS) uri
(a -> m b) ~ parsedExtractor uri

由于(URI.parseURI . toS) uri返回类型Maybe URI.URI,而MaybeMonad的实例,因此

m a ~ Maybe URI.URI 

(a -> m b) ~ (URI.URI -> m b) 

并且m b可以推断为m (URI.URI),因此>>=之后的函数(即parsedExtractor uri(的类型预计为:

(URI.URI -> m (URI.URI))

但事实并非如此。

最新更新