Is there a name for this kind of lifting a function?

跟風遠走 提交于 2019-12-10 18:09:33

问题


I wrote a Scala function:

  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
    }

Is there a name for this pattern? It is not quite an applicative functor due to cases 1 and 2. Feel free to answer with Haskell or Scala code.


回答1:


On collection it is flatten + reduce:

List(a, b).flatten.reduceOption(f)
a ++ b reduceOption f // same result



回答2:


I'm reminded of the Alternative type class in Haskell's Control.Applicative:

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

A general version of your function for any instance of Alternative might look like this:

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

For Scala, I think the closest analogy to Alternative would be the ApplicativePlus type class from Scalaz.

 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

I admit that liftOrAlternative is not a great name. After reading Twan van Laarhoven's answer, I think his suggestion of unionWith is much better at expressing what the function actually does.




回答3:


This function is similar to the Haskell containers function

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

I think unionWith is a good name for it in general. The more usual applicative operator would be an intersectionWith (aka. zipWith).

Data.Map.intersectionWith :: (a -> b -> c) -> Map k a -> Map k b -> Map k c



回答4:


In Haskell, there is something similar called liftM2.

liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r


来源:https://stackoverflow.com/questions/17188123/is-there-a-name-for-this-kind-of-lifting-a-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!