Haskell 从 URLType 中提取主机名
Haskell extract hostname from URLType
我正在使用 Network.URL 并从字符串导入 URL:
url_type $ fromJust $ importURL "https://google.com/"
Absolute (Host {protocol = HTTP True, host = "google.com", port = Nothing})
现在获取主机,我可以进行模式匹配并使用主机功能:
url' :: URLType -> Host
url' (Absolute host) = host
host $ url' $ url_type $ fromJust $ importURL "https://google.com"
那当然可以,但是 URL类型定义为:
data URLType
= Absolute Host
| HostRelative
| PathRelative
在url'
函数中,只考虑了Absolute Host
,如果url是HostRelative
或PathRelative
就会失败。我怎样才能制作一个 url'
函数来提取主机,无论是否给定?
原回答
我想你所需要的只是让你的 url'
成为一个单子函数,它 return 是一个 Maybe Host
,将 url_type
与 return
组合成另一个单子函数return 是一个 Monad
的函数(在此特定用途中恰好也是一个 Maybe
),然后使用 >>=
运算符创建一个单子链:
import Network.URL
import Data.Maybe (fromJust)
url' :: URLType -> Maybe Host
url' (Absolute host) = Just host
url' _ = Nothing
output :: Maybe Host
output = importURL "https://google.com" >>= return . url_type >>= url'
请注意 output
是 Maybe Host
。如果您接受整个操作可能会失败,则无法获得 Host
。如果您可以假设操作不会失败,那么您可以接受 fromJust
,但我相信您会问这个问题,如果是这样的话。
改进
评论中指出>> return . url_type
有点恶心。我是Haskell的新手,所以我基本上是第一个想到的就写了。可能我选择了 monadic 风格,因为我一直在研究和研究 monads 的例子,而不是应用程序。另外,我仍然是 Haskell 的新手,无法轻松地一起使用函数式、应用式和单子式样式:我只是没想过按照评论中的建议编写表达式,因为我的看起来不错。下面我根据我的知识“重新解释”评论。
有点难看的是 importURL "https://google.com" >>= return . url_type
部分,因为运算符 >>=
,其类型通常为 Monad m => m a -> (a -> m b) -> m b
,正在将其第二个参数“强制”为 return a Monad
,即使“wannabe”第二个参数 url_type
没有,因此迫使我们将其与 return
组合,以尊重 a -> m b
部分签名。我们真正想要的是在 importURL "bla"
提供的 monad 中发送 url_type
,在里面操作,并将结果留在那里,在 monad 中;也就是说,我们实际上只是将 importURL "bla"
用作 Functor
(确实如此,因为它是 Monad
)。那么我们该怎么做呢?我们通过 fmap
:
来实现
output = (fmap url_type $ importURL "https://google.com") >>= url'
我不得不使用 $
来防止 fmap
急切地吞下 importURL
,从而留下字符串。我们还没有完成:fmap
有一个等价的中缀,<$>
(注意 $
和 <$>
彼此没有任何关系),所以我们可以重写以上为
output = url_type <$> importURL "https://google.com" >>= url'
在这一点上,我想说,我们有一个比以前更丑陋的表达式,输入在它的中间。但是 =<<
到resque。它本质上是 flip (>>=)
,所以我们可以翻转两个操作数,从而得到评论中建议的表达式:
output = url' =<< url_type <$> importURL "https://google.com"
我正在使用 Network.URL 并从字符串导入 URL:
url_type $ fromJust $ importURL "https://google.com/"
Absolute (Host {protocol = HTTP True, host = "google.com", port = Nothing})
现在获取主机,我可以进行模式匹配并使用主机功能:
url' :: URLType -> Host
url' (Absolute host) = host
host $ url' $ url_type $ fromJust $ importURL "https://google.com"
那当然可以,但是 URL类型定义为:
data URLType
= Absolute Host
| HostRelative
| PathRelative
在url'
函数中,只考虑了Absolute Host
,如果url是HostRelative
或PathRelative
就会失败。我怎样才能制作一个 url'
函数来提取主机,无论是否给定?
原回答
我想你所需要的只是让你的 url'
成为一个单子函数,它 return 是一个 Maybe Host
,将 url_type
与 return
组合成另一个单子函数return 是一个 Monad
的函数(在此特定用途中恰好也是一个 Maybe
),然后使用 >>=
运算符创建一个单子链:
import Network.URL
import Data.Maybe (fromJust)
url' :: URLType -> Maybe Host
url' (Absolute host) = Just host
url' _ = Nothing
output :: Maybe Host
output = importURL "https://google.com" >>= return . url_type >>= url'
请注意 output
是 Maybe Host
。如果您接受整个操作可能会失败,则无法获得 Host
。如果您可以假设操作不会失败,那么您可以接受 fromJust
,但我相信您会问这个问题,如果是这样的话。
改进
评论中指出>> return . url_type
有点恶心。我是Haskell的新手,所以我基本上是第一个想到的就写了。可能我选择了 monadic 风格,因为我一直在研究和研究 monads 的例子,而不是应用程序。另外,我仍然是 Haskell 的新手,无法轻松地一起使用函数式、应用式和单子式样式:我只是没想过按照评论中的建议编写表达式,因为我的看起来不错。下面我根据我的知识“重新解释”评论。
有点难看的是 importURL "https://google.com" >>= return . url_type
部分,因为运算符 >>=
,其类型通常为 Monad m => m a -> (a -> m b) -> m b
,正在将其第二个参数“强制”为 return a Monad
,即使“wannabe”第二个参数 url_type
没有,因此迫使我们将其与 return
组合,以尊重 a -> m b
部分签名。我们真正想要的是在 importURL "bla"
提供的 monad 中发送 url_type
,在里面操作,并将结果留在那里,在 monad 中;也就是说,我们实际上只是将 importURL "bla"
用作 Functor
(确实如此,因为它是 Monad
)。那么我们该怎么做呢?我们通过 fmap
:
output = (fmap url_type $ importURL "https://google.com") >>= url'
我不得不使用 $
来防止 fmap
急切地吞下 importURL
,从而留下字符串。我们还没有完成:fmap
有一个等价的中缀,<$>
(注意 $
和 <$>
彼此没有任何关系),所以我们可以重写以上为
output = url_type <$> importURL "https://google.com" >>= url'
在这一点上,我想说,我们有一个比以前更丑陋的表达式,输入在它的中间。但是 =<<
到resque。它本质上是 flip (>>=)
,所以我们可以翻转两个操作数,从而得到评论中建议的表达式:
output = url' =<< url_type <$> importURL "https://google.com"