【问题标题】:Understanding the <$> operator理解 <$> 运算符
【发布时间】:2019-12-14 11:17:01
【问题描述】:

我有以下类型:

newtype Rep f a = Rep { runRep :: String -> f (String, a) }

类型 Rep f a 是一个有状态的计算,它以一个 String 作为初始状态并产生一个 (String, a) 作为计算的结果。计算的结果被包裹在函子 f 中。

Rep 的应用实例如下:

instance Monad f => Applicative (Rep f) where 
    pure x = Rep $ \s -> pure (s, x)
    Rep f <*> Rep x = Rep $ \s -> do 
        (s',rf)  <- f s 
        (s'',rx) <- x s'
        return (s'', rf rx)

Rep 的 monad 实例如下:

instance Monad f => Monad (Rep f) where 
   return x = pure x 
   Rep a >>= f = Rep $ \s -> do
    (s', ya) <- a s
    let (Rep f') = f ya
    (s'', yf) <- f' s'
    pure (s'', yf)

我有以下数据类型和功能:

data TD = Empty | Fol TD TD | Letters [Char]

data Res = Nil | Character Char | Cop Res Res | Special [Res]

findmatch (Fol a b) = do
   ra <- findmatch a
   rb <- findmatch b
   pure (Cop ra rb)

findmatch (Fol a b) = Cop <$> findmatch a <*> findmatch b

我无法理解涉及&lt;$&gt;findmatch 的第二个定义是如何工作的。我知道&lt;$&gt; 有以下类型声明:

(<$>) :: (Functor f) => (a -> b) -> f a -> f b
f <$> x = fmap f x

&lt;$&gt; 的第一个参数应该是一个函数,而第二个参数应该是一个封装在仿函数中的值。 findmatch 的结果是一个包裹在函子中的值,但是 Cop 在这种情况下是一个函数吗?我知道Cop 是一个值构造函数,它接受两个Res 类型的参数。如果将一个 Res 类型的参数传递给 Cop,我认为这是在 Cop &lt;$&gt; findmatch a 中发生的,这将返回另一个函数,该函数采用 Res 类型的值。但是,我不确定由部分应用程序产生的第二个函数返回的结果类型是什么。

感谢任何见解。

【问题讨论】:

  • 您需要查看ApplicativeRep 实例以了解为什么两者是等价的。更简短的回答是对findmatch 的两次递归调用之间没有数据依赖关系,因此Monad 实例不必要地强制一个在另一个之前运行。 Applicative 实例没有。

标签: haskell functional-programming


【解决方案1】:

但是,Cop 在这种情况下是一个函数吗?我知道Cop 是一个值构造函数,它接受两个Res 类型的参数。

是的,Cop 是一个有两个参数的函数。它的类型为Cop :: Res -&gt; Res -&gt; Res

如果将一个 Res 类型的参数传递给 Cop,这将返回另一个函数,该函数采用 Res 类型的值。

是的。 Cop &lt;$&gt; findmatch a :: Functor f =&gt; f (Res -&gt; Res)

部分应用程序产生的第二个函数返回的结果类型是什么。

这是由Cop 构造函数构造的值的类型:它正在构造Res 值。

【讨论】:

  • 既然 Cop 是一个值构造函数,我是否正确地说它接受 Res 类型的值并构造一个 Res 类型的值?
  • @ceno980 是的,就是这样。相比之下,Letters 采用 [Char] 并构造 TDCharacter 采用 Char 并构造 Res
猜你喜欢
  • 2023-03-29
  • 2012-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-06
  • 2018-11-13
  • 2021-08-12
相关资源
最近更新 更多