我正在使用一个使用whte Network.Wai
和Network.Socket.Internal
模块的Haskell程序。在这个程序中,我有一个函数,定义如下:
prepareIp :: Request -> [([Char], [Char])]
prepareIp req = [("Remote", head $ splitOn ":" $ show $ remoteHost req)]
最初,我把它作为monadic表达式(主要是为了可读性和清晰度),写成:
prepareIp :: Request -> [([Char], [Char])]
prepareIp req = do
ip <- head $ splitOn ":" $ show $ remoteHost req
[("Remote", ip)]
虽然前一个实现确实可以正常工作,但是monadic会抛出一个我无法解决的错误:它的输出类型不是[([Char], [Char])]
,而是[([Char], Char)]
- 值{ {1}}由于某种原因被转换为单个字符而不是字符串!
我还尝试使用GHCi中的模块引用以及ip
进行GHCi中的原型设计和类型检查,但无济于事,我仍然不知道导致此错误的原因。
任何人都可以告诉我为什么会发生这种类型的冲突?
答案 0 :(得分:1)
你看到这个错误的原因是因为当你不需要的时候,你试图将所有东西都推到monad中。为了说明这一点,在任何地方添加显式类型签名并为[]
交换m
:
getHostIp :: Request -> m []
getHostIp req = head $ splitOn ":" $ remoteHost req
prepareIp :: Request -> m ([Char], [Char])
prepareIp req = do
ip <- (getHostIp req :: m Char)
[("Remote" :: [Char], ip :: [Char])]
每当您看到<-
时,右侧必须有类似m a
的类型,其中m
是某种monadic类型,a
是该monadic动作的结果是。然后,<-
的左侧有a
类型。在您完全想要<-
的值时,您已使用[Char]
尝试从[Char]
中获取值。此处let
是合适的,do
表示法是多余的。由于您只返回一个值,我建议您只返回(String, String)
而不是[(String, String)]
:
prepareIp :: Request -> (String, String)
prepareIp req =
let ip = getHostIp req
in ("Remote", ip)