Построить (Проводной семак) из (a -> b -> c) и (Проводной семаб)

В качестве простого примера у меня есть это.

import Prelude hiding ((.))
import FRP.Netwire
import Control.Wire

f :: Int -> Char -> String
f = replicate

w :: => Wire s e m Int Char
w = mkSF_ fromInt
    where
        fromInt :: Int -> Char
        fromInt 1 = 'a'
        fromInt 2 = 'b'
        fromInt _ = '_'

w2 :: Wire s e m Int String
w2 = undefined -- This is where I get stuck

И я хотел бы иметь возможность создать проводник от Int до строк.

Я думаю, что это должно быть легко, но мне не повезло.

3 ответа

Решение

Другой вариант - использовать аппликативный синтаксис, который еще чище,

w2 :: Monad m => Wire s e m Int String
w2 = f <$> id <*> w

Это обобщает до

(Category cat, Applicative (cat a)) => (a -> b -> c) -> cat a b -> cat a c

Обратите внимание, что каждый Arrow вызывает вышеупомянутое ограничение.

Вам нужно разделить оригинал Int вход и разветвить оба w а также arr f, Самый простой способ объяснить это с помощью обозначения стрелки:

{-# LANGUAGE Arrows #-}
w2 :: (Monad m) => Wire s e m Int String
w2 = proc n -> do
    c <- w -< n
    returnA -< f n c

Теперь я не знаю ничего о Netwire, но это Monad m есть ограничение, потому что это необходимо для Arrow экземпляр Wire s e m,

Если вы хотите избавиться от обозначения стрелки, приведенное выше можно переписать как

w2 :: (Monad m) => Wire s e m Int String
w2 = arr (uncurry f) . (id &&& w)

Вы можете, конечно, обобщить концепцию в эту абстракцию:

-- I want to write (Arrow (~>)) => (a -> b -> c) -> (a ~> b) -> (a ~> c)!
-- Damn you TypeOperators!
arr2 :: (Arrow arr) => (a -> b -> c) -> arr a b -> arr a c
arr2 f arr = proc x -> do
    y <- arr -< x
    returnA -< f x y

Другое решение, которое я придумал, было

w2 :: Monad m => Wire s e m Int String
w2 = liftA2 ($) (mkSF_ f) w
-- or w2 = liftA2 ($) (arr f) w
-- or w2 = arr f <*> w
Другие вопросы по тегам