haskell - 无法在 Network.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
这工作正常。现在假设我要处理错误。我注意到 parseURIMaybe
表面上返回 a 我只需要对其进行模式匹配。所以我创建了一个自定义错误:
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
和Maybe
是 的一个实例Monad
,所以
m a ~ Maybe URI.URI
和
(a -> m b) ~ (URI.URI -> m b)
并且m b
可以推断为m (URI.URI)
,因此预期之后的函数(即parsedExtractor uri
)>>=
的类型为:
(URI.URI -> m (URI.URI))
但实际并非如此。
推荐阅读
- javascript - 循环一个javascript对象数组(在另一个对象内)
- java - 在 JasperSoft 7.1.1 设备中创建新的 PostgreSQL 数据源时出现问题
- python - 我的控制台没有输出任何信息?
- ios - 如果我的 20 个应用程序使用相同的框架,但每个应用程序的内容(故事)不同,是否会违反任何 Apple Store 规则?
- javascript - 我的轮播“下一步”按钮不起作用,我的轮播没有自动转换
- splunk - Splunk:发生此错误时需要帮助使用事务来获取 pcode
- xpath - 如果可用,则将嵌套兄弟中的文本与父节点中的文本连接起来
- google-apps-script - 有没有办法通过脚本编辑器动态引用 google sheet 脚本中的单元格以在另一个单元格上创建注释?
- mysql - 如何设置与关键字相同的列名?
- python - 如何输出以显示 $00.00 到小数点后第二位。代码当前生成 $00.0 或/和 $00.000000000000000