Преобразовать из обозначения стрелки
Я все еще пытаюсь получить представление о параллелях между обозначениями стрелок и семантикой классов типов стрелок, определенных в Haskell. В частности, этот вопрос, кажется, имеет очень канонический пример небольшого счетчика, написанного стрелкой:
counter :: ArrowCircuit a => a Bool Int
counter = proc reset -> do
rec output <- returnA -< if reset then 0 else next
next <- delay 0 -< output+1
returnA -< output
Может кто-нибудь показать мне, как преобразовать это обратно в Haskell2010 без стрелки?
2 ответа
Решение
{- |
+---------+
>Bool>--------------> |
| >------------------>Int>
+---------+ | arr f |
/----> delay 0 >---> >---------\
| +---------+ | | |
| +---------+ |
| |
\--------------------------------------/
-}
counter' :: ArrowCircuit a => a Bool Int
counter' = loop $ second (delay 0) >>> arr f
where
f (reset, next) = let output = if reset then 0 else next
next' = output + 1
in (output, next')
Рекурсивный rec
часть реализована с использованием loop
, Внутренняя часть, которая преобразует reset
в output
с помощью next
(и производит новый next
значение) это просто чистая функция с двумя входами и двумя выходами.
Параллелизмом в функциональном коде было бы использование состояния op. в сгибе
import Data.List
counter :: (Int, Int) -> Bool -> (Int, Int)
counter (_, previous_next) reset =
let output = if reset then 0 else previous_next
next = output +1
in (output, next)
runCounter :: [Bool] -> (Int, Int)
runCounter = foldl' counter (0,1)
main = do
let resets = [True, False, True, False, False]
result = fst $ runCounter resets
print result