No já bych chtěl obecné řešení na sčítání datových typů, které se sčítat umí. Jsem ochoten smířit se s tím, že string se v Haskellu sčítat neumí. Co třeba vektor, šlo by to? Neznám tu správnou syntaxi v Haskellu, něco takového by fungovalo?
Umí se sčítat všechny typy, co jsou Num. Základní seznam je tady:
http://hackage.haskell.org/package/base-4.8.2.0/docs/Prelude.html#t:NumPak existuje forma "sčítání" Monoid (operátor <> z Data.Monoid). Ten je základně definovaný pro tyhle typy:
http://hackage.haskell.org/package/base-4.8.2.0/docs/Data-Monoid.html, je definovaný i pro čísla, ale přes newtype Sum a Product, protože obojí je Monoid a je potřeba si zvolit.
Oni haskellisti když definují typeclassy, tak typicky vymýšlejí nějaké zákony, které by ta TypeClass měla splňovat, aby se na to dalo spolehnout a ty funkce, které závisí např. na "Num" dávaly rozumné výsledky pro jakýkoliv typ Num, který do ní vleze. Což pro string úplně nefunguje (co String krát String?). Takže na práci se stringama mají jinou typeclass. Ale není problém si definovat vlastní typeclass s vlastníma funkcema třeba takhle:
class Scitej a where
.+. :: a -> a -> a
instance Scitej Int where
.+. = +
instance Scitej String where
.+. = ++
incrementTVar :: Scitej a => TVar a -> a -> STM ()
incrementTVar v k = atomically (modifyTVar' v (.+. k))
Nepleteš se, retry to neumí, ale zkus přijmout, že retry i případný timeout je naprosto minoritní funkcionalita, kterou si snadno doděláš.
No úplně minoritní není, protože prakticky jediný způsob, jak to dodělat, je udělat nějakou condition variable, která globálně při výstupu z transakce pošle signál.
Další věc je, že v Haskellu jediný způsob, jak přistupovat k těmhe proměnným, je v "atomically" bloku. V C++ nikoliv. Takže když ti někdo v kódu změní ta data mimo "transakci", tak hodně štěstí s hledáním chyb...
import Data.Vector
main = do
let v1 = fromList [0, 0]
let v2 = fromList [1, 1]
v0 <- newTVarIO v1 :: IO (TVar Data.Vector)
p0 <- async (tVarIncrementingProcess v0 v2)
wait p0
Tak otázka je, co myslíte tady pod pojmem sčítání. Vector má Monoid (tzn. <>, aneb append). Ale mohl byste si to definovat třeba jako:
instance Scitej a => Scitej (Vector a) where
.+. = Data.Vector.zipWith (+)
A teď to bude fungovat na vektor s jakýmkoliv obsahem, jehož obsah je instancí Scitej.