3

我写了一个Scala函数:

  def liftOrIdentity[T](f: (T, T) => T) = (a: Option[T], b: Option[T]) =>
    (a, b) match {
      case (Some(a), None) => Some(a)
      case (None, Some(b)) => Some(b)
      case (Some(a), Some(b)) => Some(f(a, b))
      case (None, None) => None
    }

这种模式有名字吗?由于案例 1 和 2,它不是一个适用的函子。请随意使用 Haskell 或 Scala 代码回答。

4

4 回答 4

9

收集时为flatten+ reduce

List(a, b).flatten.reduceOption(f)
a ++ b reduceOption f // same result
于 2013-06-19T10:03:43.923 回答
7

我想起了AlternativeHaskell 中的类型类Control.Applicative

class Applicative f => Alternative f where
    empty :: f a
    (<|>) :: f a -> f a -> f a

任何实例的函数的通用版本Alternative可能如下所示:

liftOrAlternative :: (Alternative f) => (a -> a -> a) -> f a -> f a -> f a
liftOrAlternative f a b = f <$> a <*> b <|> a <|> b

ghci> liftOrAlternative (+) (Just 1) Nothing
Just 1
ghci> liftOrAlternative (+) (Just 1) (Just 2)
Just 3
ghci> liftOrAlternative (+) Nothing Nothing
Nothing

对于 Scala,我认为最接近的类比是来自 ScalazAlternative的类型类。ApplicativePlus

 def liftOrAlternative[A, F[_]: ApplicativePlus](f: (A, A) => A)(a: F[A], b: F[A]): F[A] =
   f.lift[F].apply(a, b) <+> a <+> b

我承认这liftOrAlternative不是一个好名字。在阅读了 Twan van Laarhoven 的回答后,我认为他的建议unionWith更好地表达了函数的实际作用。

于 2013-06-19T12:38:34.587 回答
4

该功能类似于 Haskell 容器功能

Data.Map.unionWith :: (a -> a -> a) -> Map k a -> Map k a -> Map k a

我认为 unionWith 通常是一个好名字。更常见的应用运算符是intersectionWith(aka. zipWith)。

Data.Map.intersectionWith :: (a -> b -> c) -> Map k a -> Map k b -> Map k c
于 2013-06-19T13:17:36.957 回答
-1

在 Haskell 中,有一个类似的东西叫做liftM2

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
于 2013-06-19T10:08:44.697 回答