我有一大堆的数据结构的像data Foo = Foo {a :: Type1, b :: Type2} deriving (Something)与Type1和Type2是始终不同(一般是原始类型,但它是不相关的),并在不同的数字.
我来这里有很多功能
justFooify :: Maybe Type1 -> Maybe Type2 -> Maybe Foo
justFooify f b =
| isNothing f = Nothing
| isNothing b = Nothing
| otherwise = Just $ Foo (fromJust f) (fromJust b)
Run Code Online (Sandbox Code Playgroud)
有什么我想念的吗?第三次这样的功能之后,我写了我来想,也许它可能是太多了.
你需要申请人!
import Control.Applicative
justFooify :: Maybe Type1 -> Maybe Type2 -> Maybe Foo
justFooify f b = Foo <$> f <*> b
Run Code Online (Sandbox Code Playgroud)
或者您可以liftA2在此示例中使用:
justFooify = liftA2 Foo
Run Code Online (Sandbox Code Playgroud)
它表现得像liftM2,但是Applicative.如果你有更多的参数,只需使用更多的<*>s:
data Test = Test String Int Double String deriving (Eq, Show)
buildTest :: Maybe String -> Maybe Int -> Maybe Double -> Maybe String -> Maybe Test
buildTest s1 i d s2 = Test <$> s1 <*> i <*> d <*> s2
Run Code Online (Sandbox Code Playgroud)
什么是Applicatives?他们基本上是一个更强大Functor,更强大Monad,他们介于两者之间.类型类的定义是
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
-- plus a few more things that aren't important right now
Run Code Online (Sandbox Code Playgroud)
如果你Applicative也是一个Monad,那么pure就是一样的return(事实上,有些人觉得有return不正确,我们应该只有pure).然而,<*>运营商使他们比Functors 更强大.它为您提供了一种将函数放入数据结构的方法,然后将该函数应用于也包含在数据结构中的值.所以当你有类似的东西时
> :t Test -- Our construct
Test :: String -> Int -> Double -> String -> Test
> :t fmap Test -- also (Test <$>), since (<$>) = fmap
fmap Test :: Functor f => f String -> f (Int -> Double -> String -> Test)
Run Code Online (Sandbox Code Playgroud)
我们看到它在a中构造一个函数Functor,因为Test它需要多个参数.所以Test <$> Just "a"有型Maybe (Int -> Double -> String -> Test).只是Functor和fmap,我们不能在内部应用任何东西Maybe,但<*>我们可以.每个应用程序都<*>将一个参数应用于该内部Functor,现在应该将其视为一个Applicative.
关于它的另一个方便的事情是它适用于所有 Monad(当前定义它们的Applicative实例).这意味着列表,IO一个参数的功能Either e,解析器等.例如,如果您从用户那里获得输入以构建Test:
askString :: IO String
askInt :: IO Int
askDouble :: IO Double
-- whatever you might put here to prompt for it, or maybe it's read from disk, etc
askForTest :: IO Test
askForTest = Test <$> askString <*> askInt <*> askDouble <*> askString
Run Code Online (Sandbox Code Playgroud)
它仍然有效.这是Applicatives的力量.
仅供参考,在GHC 7.10中,将实施Functor-Applicative-Monad提案.这将改变Monadfrom 的定义
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Run Code Online (Sandbox Code Playgroud)
至
class Applicative m => Monad m where
return :: a -> m a
return = pure
(>>=) :: m a -> (a -> m b) -> m b
join :: m (m a) -> m a
Run Code Online (Sandbox Code Playgroud)
(或多或少).这将打破一些旧代码,但许多人对此感到兴奋,因为它意味着所有Monads都是Applicative并且所有Applicative都是Functors,我们将拥有这些代数对象的全部功能.
| 归档时间: |
|
| 查看次数: |
117 次 |
| 最近记录: |