繁体   English   中英

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

[英]Use cases for functor/applicative/monad instances for functions

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

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

涉及Functor和Applicative函数实例的常见模式是例如(+) <$> (*2) <*> (subtract 1) 当您必须使用单个值提供一系列函数时,这尤其有用。 在这种情况下,上述等价于\\x -> (x * 2) + (x - 1) 虽然这与LiftA2非常接近, LiftA2您可以无限延长此模式。 如果你有一个f函数来取5个参数,比如a -> a -> a -> a -> a -> b你可能会喜欢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

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

这样做的一种方式是使用Data.Functor.Compose ,其寄生在所述Applicative的实例(->) am ,得到Applicative实例,以使组合物:

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

还有其他方法,比如创建自己的newtype,或者使用基础库或其他库中的现成 newtypes

这里是我用来解决Diamond Kata的绑定函数的应用。 采用一个简单的函数来反映其输入,丢弃最后一个元素

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 (++)

以下是我对此Kata的完整实现: https//github.com/enolive/exercism/blob/master/haskell/diamond/src/Diamond.hs

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM