![](/img/trans.png)
[英]Can GHC derive Functor and Applicative instances for a monad transformer?
[英]Use cases for functor/applicative/monad instances for functions
Haskell具有为函数定义的Functor
, Applicative
和Monad
实例(特别是部分应用的类型(->) 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
(其中m
是Applicative
)视为Applicative
s本身。 编写验证器或解析器时经常会发生这种情况。
这样做的一种方式是使用Data.Functor.Compose
,其寄生在所述Applicative
的实例(->) a
和m
,得到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
这里是我用来解决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.