【问题标题】:Haskell converting [Char] to CharHaskell 将 [Char] 转换为 Char
【发布时间】:2015-05-29 18:13:54
【问题描述】:

我正在开发一个使用白色 Network.WaiNetwork.Socket.Internal 模块的 Haskell 程序。在这个程序中,我有一个函数,定义如下:

prepareIp :: Request -> [([Char], [Char])]
prepareIp req = [("Remote", head $ splitOn ":" $ show $ remoteHost req)]

最初,我把它做成一个单子表达式(主要是为了可读性和清晰性),写成:

prepareIp :: Request -> [([Char], [Char])]
prepareIp req = do
     ip <- head $ splitOn ":" $ show $ remoteHost req
     [("Remote", ip)]

虽然前一个实现确实可以正常工作,但单子实现却抛出了一个我无法理解的错误:它的输出类型不是[([Char], [Char])],而是[([Char], Char)]——对于某些人来说,值ip是原因,变成了单个字符而不是字符串!

我还尝试在 GHCi 中对此进行原型设计,并使用模块引用以及 GHCi 中的 :t 进行类型检查,但无济于事,我仍然不知道是什么导致了这个错误。

谁能告诉我为什么会发生这种类型冲突?

【问题讨论】:

  • 你为什么要返回一个列表,看起来你最好用Request -&gt; (String, String)String只是[Char]的别名),然后就用@987654332 @,如果这对您来说还不够可读,那么请使用本地 let,例如 prepareIp req = let ip = head $ splitOn ":" $ show $ remoteHost req in ("Remote", ip),尽管为了便于阅读,混入了更多空格。
  • 您也可能应该在remoteHost req 返回的SockAddr 上进行模式匹配以提取IP(作为HostAddressHostAddress6),而不是将其转换为要切片的字符串和骰子。
  • 至于为什么它认为你需要Char而不是[Char],这是因为当你拥有ip &lt;-时,它会从&lt;-右侧的列表中提取每个元素,并且由于在这种情况下head 返回一个String,它等价于[Char],编译器期望ip 具有Char 类型。你真的只需要一个let,而不是单子。
  • @bheklilr 我不知道Word32 上的模式匹配是可能的(因为这就是HostAddress 的全部内容——这怎么可能呢?
  • 您将在 SockAddr 的构造函数上进行模式匹配,而不是在 Word32 本身:case remoteHost req of { SockAddrInet port addr -&gt; ...; SockAddrInet6 port flow addr6 scope -&gt; ...; SockAddrUnix addr -&gt; ...}

标签: haskell type-systems


【解决方案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])]

每当您看到&lt;- 时,右侧必须有一些类型,例如m a,其中m 是一些单子类型,a 是该单子操作的结果。然后,&lt;- 的左侧有a 类型。在这里,您使用了&lt;- 来尝试从[Char] 中获取值,而您实际上只是完全想要[Char] 的值。 let 在这里是合适的,do 表示法是多余的。由于您也只返回一个值,我建议只返回 (String, String) 而不是 [(String, String)]

prepareIp :: Request -> (String, String)
prepareIp req =
    let ip = getHostIp req
    in ("Remote", ip)

【讨论】:

    猜你喜欢
    • 2020-04-11
    • 1970-01-01
    • 2010-10-12
    • 2021-04-29
    • 2013-10-18
    • 2012-01-15
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多