函数的functor / applicative / monad实例的用例

时间:2017-10-08 12:44:42

标签: haskell functional-programming

Haskell为标准库中的函数(特别是部分应用的类型Functor)定义了ApplicativeMonad(->) a个实例,围绕函数组合构建。

理解这些实例是一个很好的心灵弯曲练习,但我的问题是关于这些实例的实际用法。我很高兴听到人们使用这些实际代码的现实场景。

3 个答案:

答案 0 :(得分:7)

涉及Functor和Applicative函数实例的常见模式是例如(+) <$> (*2) <*> (subtract 1)。当您必须使用单个值提供一系列函数时,这尤其有用。在这种情况下,上述内容相当于\x -> (x * 2) + (x - 1)。虽然这非常接近LiftA2,但您可以无限期地扩展此模式。如果你有f函数来获取a -> a -> a -> a -> a -> b这样的5个参数,你可能会喜欢f <$> (+2) <*> (*2) <*> (+1) <*> (subtract 3) <*> (/2)并用单个值来提供它。就像在下面的情况一样;

Prelude> (,,,,) <$> (+2) <*> (*2) <*> (+1) <*> (subtract 3) <*> (/2) $ 10
(12.0,20.0,11.0,7.0,5.0)

编辑:@Will Ness在另一个主题下对我的评论进行重新评论的信用,这里有一个关于功能的应用的美妙用法;

Prelude> let isAscending = and . (zipWith (<=) <*> drop 1)
Prelude> isAscending [1,2,3,4]
True
Prelude> isAscending [1,2,5,4]
False

答案 1 :(得分:4)

有时您希望将a -> m b形式的函数(mApplicative)视为Applicative自身。编写验证器或解析器时经常会发生这种情况。

执行此操作的一种方法是使用Data.Functor.ComposeApplicative实例(->) amApplicative实例提供import Control.Applicative import Data.Functor.Compose type Star m a b = Compose ((->) a) m b readPrompt :: Star IO String Int readPrompt = Compose $ \prompt -> do putStrLn $ prompt ++ ":" readLn main :: IO () main = do r <- getCompose (liftA2 (,) readPrompt readPrompt) "write number" print r 实例组合物:

@include('banners.bottom')

还有其他方法,例如创建自己的新类型,或使用 base 或其他库中的ready-made newtypes

答案 2 :(得分:0)

这里是我用来解决Diamond Kata的bind函数的一个应用程序。采取一个简单的函数来镜像其输入,丢弃最后一个元素

mirror :: [a] -> [a]
mirror xs = xs ++ (reverse . init) xs

让我们重写一下

mirror xs = (++) xs ((reverse . init) xs)
mirror xs = flip (++) ((reverse . init) xs) xs
mirror xs = (reverse . init >>= flip (++)) xs
mirror = reverse . init >>= flip (++)

这是我完整实施此卡塔的方法:https://github.com/enolive/exercism/blob/master/haskell/diamond/src/Diamond.hs