{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE UndecidableInstances #-}
import Data.STRef (STRef, newSTRef, readSTRef, modifySTRef)
import Control
.Monad (when
) import Control
.Monad.ST
(ST
, runST
)
class (Monad m
) => NumMod l r m
where (+=) :: l -> r -> m ()
(-=) :: l -> r -> m ()
(*=) :: l -> r -> m ()
instance Num a
=> NumMod
(STRef s a
) (STRef s a
) (ST s
) where a += b = readSTRef b >>= \b -> modifySTRef a ((+) b)
a
-= b
= readSTRef b
>>= \b
-> modifySTRef a
((+) (negate b
)) a *= b = readSTRef b >>= \b -> modifySTRef a ((*) b)
instance Num a
=> NumMod
(STRef s a
) a
(ST s
) where a += b = modifySTRef a ((+) b)
a
-= b
= modifySTRef a
((+) (negate b
)) a *= b = modifySTRef a ((*) b)
var = newSTRef
def :: (forall s. ST s (STRef s a)) -> a
def = \x -> runST $ x >>= readSTRef
class BooleanL b
where toBool
:: b
-> Bool instance BooleanL
Bool where toBool
= id instance (Num a
, Eq a
) => BooleanL a
where toBool n
= n
/= 0
while :: (BooleanL a) => STRef s a -> ST s () -> ST s ()
while i st
= fmap toBool
(readSTRef i
) >>= \p
-> when p $ st >> while i st
factorial n = def $ do
assert (n >= 0) "Negative factorial"
ret <- var 1
i <- var n
while i $ do
ret *= i
i -= 1
main
= print . factorial
$ 1000
ey0jIExBTkdVQUdFIEZsZXhpYmxlSW5zdGFuY2VzICMtfQp7LSMgTEFOR1VBR0UgUmFua05UeXBlcyAjLX0Key0jIExBTkdVQUdFIE11bHRpUGFyYW1UeXBlQ2xhc3NlcyAjLX0Key0jIExBTkdVQUdFIFVuZGVjaWRhYmxlSW5zdGFuY2VzICMtfQoKaW1wb3J0IERhdGEuU1RSZWYgICAgKFNUUmVmLCBuZXdTVFJlZiwgcmVhZFNUUmVmLCBtb2RpZnlTVFJlZikKaW1wb3J0IENvbnRyb2wuTW9uYWQgKHdoZW4pCmltcG9ydCBDb250cm9sLk1vbmFkLlNUIChTVCwgcnVuU1QpCgpjbGFzcyAoTW9uYWQgbSkgPT4gTnVtTW9kIGwgciBtIHdoZXJlCiAgKCs9KSA6OiBsIC0+IHIgLT4gbSAoKQogICgtPSkgOjogbCAtPiByIC0+IG0gKCkKICAoKj0pIDo6IGwgLT4gciAtPiBtICgpCgppbnN0YW5jZSBOdW0gYSA9PiBOdW1Nb2QgKFNUUmVmIHMgYSkgKFNUUmVmIHMgYSkgKFNUIHMpIHdoZXJlCiAgYSArPSBiICAgID0gcmVhZFNUUmVmIGIgPj49IFxiIC0+IG1vZGlmeVNUUmVmIGEgKCgrKSBiKQogIGEgLT0gYiAgICA9IHJlYWRTVFJlZiBiID4+PSBcYiAtPiBtb2RpZnlTVFJlZiBhICgoKykgKG5lZ2F0ZSBiKSkKICBhICo9IGIgICAgPSByZWFkU1RSZWYgYiA+Pj0gXGIgLT4gbW9kaWZ5U1RSZWYgYSAoKCopIGIpCgppbnN0YW5jZSBOdW0gYSA9PiBOdW1Nb2QgKFNUUmVmIHMgYSkgYSAoU1Qgcykgd2hlcmUKICBhICs9IGIgICAgPSBtb2RpZnlTVFJlZiBhICgoKykgYikKICBhIC09IGIgICAgPSBtb2RpZnlTVFJlZiBhICgoKykgKG5lZ2F0ZSBiKSkKICBhICo9IGIgICAgPSBtb2RpZnlTVFJlZiBhICgoKikgYikKCnZhciA9IG5ld1NUUmVmCgpkZWYgOjogKGZvcmFsbCBzLiBTVCBzIChTVFJlZiBzIGEpKSAtPiBhCmRlZiA9IFx4IC0+IHJ1blNUICQgeCA+Pj0gcmVhZFNUUmVmCgpjbGFzcyBCb29sZWFuTCBiIHdoZXJlIHRvQm9vbCA6OiBiIC0+IEJvb2wKaW5zdGFuY2UgQm9vbGVhbkwgQm9vbCB3aGVyZSB0b0Jvb2wgPSBpZAppbnN0YW5jZSAoTnVtIGEsIEVxIGEpID0+IEJvb2xlYW5MIGEgd2hlcmUgdG9Cb29sIG4gPSBuIC89IDAKCndoaWxlIDo6IChCb29sZWFuTCBhKSA9PiBTVFJlZiBzIGEgLT4gU1QgcyAoKSAtPiBTVCBzICgpCndoaWxlIGkgc3QgPSBmbWFwIHRvQm9vbCAocmVhZFNUUmVmIGkpID4+PSBccCAtPgogICAgICAgICAgICAgd2hlbiBwICQgc3QgPj4gd2hpbGUgaSBzdAoKYXNzZXJ0IGIgc3RyID0gd2hlbiAobm90IGIpIC4gcmV0dXJuICQgZXJyb3Igc3RyCgpmYWN0b3JpYWwgOjogSW50ZWdlciAtPiBJbnRlZ2VyCmZhY3RvcmlhbCBuID0gZGVmICQgZG8KICAgIGFzc2VydCAobiA+PSAwKSAiTmVnYXRpdmUgZmFjdG9yaWFsIgogICAgcmV0IDwtIHZhciAxCiAgICBpICAgPC0gdmFyIG4KICAgIHdoaWxlIGkgJCBkbwogICAgICAgIHJldCAqPSBpCiAgICAgICAgaSAtPSAxCiAgICByZXR1cm4gcmV0CgptYWluID0gcHJpbnQgLiBmYWN0b3JpYWwgJCAxMDAw