gpt4 book ai didi

haskell - 这是使用 liftM 的情况吗?

转载 作者:行者123 更新时间:2023-12-02 17:08:41 26 4
gpt4 key购买 nike

我有以下功能:

sendq :: Socket -> B.ByteString -> String -> IO PortNumber -> IO ()
sendq s datastring host port = do
hostAddr <- inet_addr host
sendAllTo s datastring (SockAddrInet port hostAddr)

而 sendAllTo 具有函数签名

sendAllTo :: Socket -> ByteString -> SockAddr -> IO ()

问题是从以前的函数中我得到了一个 IO PortNumber,其中 SockAddr 仅接受一个 PortNumber。我尝试通过将 sendAllTo 提升到 IO monad 中来使这两者兼容:

liftM sendAllTo s datastring (SockAddrInet port hostAddr)

但没有喜悦。告诉我一些关于许多争论的事情。这是 liftM 的案例吗?如何正确应用?

最佳答案

liftM和 friend 的目的是将功能提升到一元设置,就像 Applicative 一样。组合器可以。

liftM :: Monad m => (s -> t) -> m s -> m t

您尝试的代码有两个问题。一是缺少括号。

liftM sendAllTo :: IO Socket -> IO (ByteString -> SockAddr -> IO ())

这不是你的意思。另一个问题是

sendAllTo :: Socket -> ByteString -> SockAddr -> IO ()

是一个单子(monad)操作,因此提升它将提供两层 IO 。通常的方法是将应用程序的纯前缀加上括号,就像这样

liftM (sendAllTo s datastring) :: IO SockAddr -> IO (IO ())

然后您可以使用 liftM2 构建参数.

liftM2 SockAddrInet ioport (inet_adder host) :: IO SockAddr

这给了你

liftM (sendAllTo s datastring) (liftM2 SockAddrInet ioport (inet_adder host))
:: IO (IO ())

它实际上不会实现任何目标,因为它解释了如何计算一个操作,但实际上并没有调用它!这就是你需要的地方

join (liftM (sendAllTo s datastring) (liftM2 SockAddrInet ioport (inet_addr host)))
:: IO ()

或者,更紧凑

sendAllTo s datastring =<< liftM2 SockAddrInet ioport (inet_adder host)

插头。Strathclyde Haskell Enhancement支持idiom brackets ,其中

(|f a1 .. an|) :: m t如果f :: s1 -> ... -> sn -> ta1 :: m s1 ... an :: m sn .

这些对 Applicative m 执行相同的工作作为liftM家庭为单子(monad)做,治疗f作为纯 n 元函数和 a1 ..an作为有效的论据。 Monad s 可以而且应该是 Applicative也这样

(|SockAddrInet ioprot (inet_addr host)|) :: IO SockAddr

(|(sendAllTo s datastring) (|SockAddrInet ioprot (inet_addr host)|)|) :: IO (IO ())

然后,该符号允许您调用如上所述的计算单子(monad)计算,并带有后缀 @ .

(|(sendAllTo s datastring) (|SockAddrInet ioprot (inet_addr host)|) @|) :: IO ()

请注意,我仍然将应用程序的纯前缀括起来,以便 f模板的整体是(sendAllTo s datastring) 。该表示法允许您在任何位置用 ~ 标记纯参数。 ,所以你可以这样写

(|sendAllTo ~s ~datastring (|SockAddrInet ioprot (inet_addr host)|) @|) :: IO ()

如果心情好的话。

咆哮。我们花费了太多的精力来找出正确的liftM , join , =<< , do , (|...~...@|)标点符号,以解释如何在效果解释上下文(此处为())中将类型分割为值解释内核(此处为IO)。如果这种向上切割在类型中更明确地进行,那么我们的程序中应该需要更少的噪音来将值和计算对齐。我应该更喜欢计算机来推断 ~ 在哪里和@标记已通过,但就目前情况而言,Haskell 类型的文档过于模糊,无法实现这一点。

关于haskell - 这是使用 liftM 的情况吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12025658/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com