Fel*_*lix 3 haskell functional-programming scala option lifting
我写了一个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
}
Run Code Online (Sandbox Code Playgroud)
这个模式有名字吗?由于案例1和2,它不是一个应用程序仿函数.可以随意回答Haskell或Scala代码.
在收集它是flatten+ reduce:
List(a, b).flatten.reduceOption(f)
a ++ b reduceOption f // same result
Run Code Online (Sandbox Code Playgroud)
我想起了AlternativeHaskell中的类型类Control.Applicative:
class Applicative f => Alternative f where
empty :: f a
(<|>) :: f a -> f a -> f a
Run Code Online (Sandbox Code Playgroud)
任何实例的函数的通用版本Alternative可能如下所示:
liftOrAlternative :: (Alternative f) => (a -> a -> a) -> f a -> f a -> f a
liftOrAlternative f a b = f <$> a <*> b <|> a <|> b
Run Code Online (Sandbox Code Playgroud)
ghci> liftOrAlternative (+) (Just 1) Nothing
Just 1
ghci> liftOrAlternative (+) (Just 1) (Just 2)
Just 3
ghci> liftOrAlternative (+) Nothing Nothing
Nothing
Run Code Online (Sandbox Code Playgroud)
对于Scala,我认为最接近的类似于Scalaz Alternative的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
Run Code Online (Sandbox Code Playgroud)
我承认这liftOrAlternative不是一个好名字.在阅读了Twan van Laarhoven的回答之后,我认为他的建议unionWith在表达函数的实际功能方面要好得多.