Подтвердить что ты не робот

Примеры использования для экземпляров functor/applative/monad для функций

Haskell имеет Functor, Applicative и Monad экземпляры, определенные для функций (в частности, частично применяемого типа (->) a) в стандартной библиотеке, построенных вокруг композиции функций.

Понимание этих случаев - это отличное упражнение с умственным уклоном, но мой вопрос здесь о практическом использовании этих экземпляров. Я был бы рад услышать о реалистичных сценариях, где люди использовали их для практического кода.

4b9b3361

Ответ 1

Общий шаблон, который включает в себя Functor и аппликативные экземпляры функций, например, (+) <$> (*2) <*> (subtract 1). Это особенно полезно, когда вам нужно подавать серию функций с одним значением. В этом случае приведенное выше эквивалентно \x -> (x * 2) + (x - 1). Хотя это очень близко к 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

Ответ 2

Иногда вы хотите рассматривать функции формы a -> m b (где m является Applicative) как Applicative. Это часто случается при написании валидаторов или парсеров.

Один из способов сделать это - использовать 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

Существуют и другие способы, например создание собственного типа new, или использование готового newtypes из базы или других библиотек.