Рассмотрим следующий код:Полиморфные функции цепочки для постоянных моделей
import Database.Persist
import Database.Persist.TH
import Database.Persist.Sqlite
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Model1
fieldA Int
fieldB String
Model2
fieldC String
fieldD Double Maybe
|]
(>->) :: Maybe a -> Maybe a -> Maybe a
(>->) (Just x) _ = Just x
(>->) _ b = b
heavyComputation1 :: [String] -> Maybe Model1
heavyComputation1 input = undefined
heavyComputation2 :: [String] -> Maybe Model1
heavyComputation2 input = undefined
heavyComputation3 :: [String] -> Maybe Model2
heavyComputation3 input = undefined
heavyComputation4 :: [String] -> Maybe Model2
heavyComputation4 input = undefined
doTheWork :: [String] -> IO()
doTheWork input = do
let result = (heavyComputation1 input)
>-> (heavyComputation2 input)
>-> (heavyComputation3 input)
>-> (heavyComputation4 input)
case result of
Just x -> runSqlite "base.db" $ do insert x; return()
Nothing -> return()
Это не компилируется (конечно). Только один из heavyComputation
s будет выдавать значение для данного входа. Ожидается, что (>->)
прекратит вычисление CPU, когда будет произведено первое значение.
Вопросы:
- Есть что-нибудь, как мой
(>->)
уже определен? - Какой тип должен иметь
(>->)
? Я пытался сделать что-то вроде(>->) :: forall a. PersistEntity a => Maybe a -> Maybe a -> Maybe a
, но я, очевидно, не понимаюforall
, поскольку он, похоже, не помогает.
Возможно, вся моя конструкция неправильная. Идея заключается в том, чтобы получить один из Model
с построенными из входного и пропустить ненужные вычисления без такого уродства:
doTheWorkUgly :: [String] -> IO()
doTheWorkUgly input = do
case heavyComputation1 input of
Just x -> runSqlite "abc.db" $ do insert x; return()
Nothing -> case heavyComputation2 input of
Just x -> runSqlite "abc.db" $ do insert x; return()
Nothing -> case heavyComputation3 input of
Just x -> runSqlite "abc.db" $ do insert x; return()
Nothing -> case heavyComputation4 input of
Just x -> runSqlite "abc.db" $ do insert x; return()
Nothing -> return()
Моя идея заключается в том, чтобы иметь result
быть любой из моделей. insert
может полиморфно записывать в БД. Я бы хотел, чтобы мой короткозамкнутый «цепной» оператор тоже был полиморфным. Помогите!
Что касается типа, тип, который у вас есть, в порядке. Зачем ограничивать его 'PersistEntity'? Но, что касается вашего первого вопроса: он уже существует! Он называется '(<|>)' в модуле 'Control.Applicative'. –
'Альтернатива'! Это то, что я искал! – Tomo