[Haskell-cafe] [Long] 'Fun' with types
Maciej Piechotka
uzytkownik2 at gmail.com
Thu Sep 3 18:34:07 EDT 2009
I'm somehow experimenting with GADT. I'm implementing FRP system and I
get such error:
Occurs check: cannot construct the infinite type: a = (a, b)
In the pattern: CircuitSplit f g
In the definition of `createChannel':
createChannel (CircuitSplit f g)
= let
(df, cf) = createChannel f
(dg, cg) = createChannel g
....
in
(df <<< dg,
Map.map merge
$ Map.unionWith
(\ (First x) (Second y) -> Both x y)
(Map.map First cf)
(Map.map Second cf))
On code:
import Control.Applicative
import Control.Arrow
import Control.Category (Category)
import qualified Control.Category
import Control.Monad
import Control.Monad.Fix
import Data.IORef
import Data.Monoid hiding (First)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Unique
import Foreign
import Foreign.C
import Unsafe.Coerce
-- | "CSignal" is a continous signal - i.e. signal which have a value at
each
-- point of time
data CSignal a = CSignal (IO a)
instance Functor CSignal where
f `fmap` (CSignal v) = CSignal $ f <$> v
instance Applicative CSignal where
pure x = CSignal $ pure x
(CSignal f) <*> (CSignal v) = CSignal $ f <*> v
-- | "DSignal" is a discret signal - i.e. signal which is point-like.
data DSignal a = DSignal (Map Unique ((a -> IO ()) -> IO ()))
instance Functor DSignal where
f `fmap` (DSignal l) = DSignal $ Map.map (. (. f)) l
instance Monoid (DSignal a) where
mempty = DSignal Map.empty
(DSignal l) `mappend` (DSignal s) = DSignal $ Map.union l s
-- | Convers the discret signal into a continous signal
readAndCacheSignal :: a -- ^ Inital value
-> DSignal a -- ^ Discret signal
-> IO (CSignal a) -- ^ Continous signal
readAndCacheSignal v (DSignal l) = do
vr <- newIORef v
Map.fold (>>) (return ()) $ Map.map ($ writeIORef vr) l
return $ CSignal $ readIORef vr
data Circuit a b where
CircuitCSignal :: CSignal a -> Circuit () a
CircuitDSignal :: DSignal a -> Circuit () (Maybe a)
CircuitArr :: Kleisli IO a b -> Circuit a b
CircuitJoint :: Circuit b c -> Circuit a b -> Circuit a c
CircuitSplit :: Circuit a c -> Circuit b d -> Circuit (a, b) (c, d)
CircuitChoice :: Circuit a c -> Circuit b d
-> Circuit (Either a b) (Either c d)
CircuitLoop :: Circuit (a, c) (b, c) -> Circuit a b
instance Category Circuit where
id = CircuitArr returnA
f . g = CircuitJoint f g
instance Arrow Circuit where
arr f = CircuitArr $ arr f
first = flip CircuitSplit returnA
second = CircuitSplit returnA
(***) = CircuitSplit
instance ArrowChoice Circuit where
left = flip CircuitChoice returnA
right = CircuitChoice returnA
(+++) = CircuitChoice
instance ArrowLoop Circuit where
loop = CircuitLoop
data CircuitChannel a b where
CircuitChannel :: Kleisli IO (c, a) b
-> ((c -> IO ()) -> IO ())
-> CircuitChannel a b
data ChannelJoin a b = First a
| Second b
| Both a b
createChannel :: Circuit a b
-> (Kleisli IO a b, Map Unique (CircuitChannel a b))
createChannel (CircuitCSignal (CSignal v)) = (Kleisli (const v),
Map.empty)
createChannel (CircuitDSignal (DSignal l)) =
(arr $ const Nothing, Map.map (CircuitChannel (arr $ Just . snd)) l)
createChannel (CircuitArr a) = (a, Map.empty)
createChannel (CircuitJoint f g) =
let (df, cf) = createChannel f
(dg, cg) = createChannel g
merge (First (CircuitChannel a r)) =
CircuitChannel (dg <<< a) r
merge (Second (CircuitChannel a r)) =
CircuitChannel (a <<< second df) r
merge (Both (CircuitChannel a r) (CircuitChannel b _)) =
CircuitChannel (proc (d, v) -> do v' <- b -< (d, v)
a -< (d, v')) r
in (df <<< dg,
Map.map merge $
Map.unionWith (\(First x) (Second y) -> Both x y)
(Map.map First cf) (Map.map Second cf))
createChannel (CircuitSplit f g) =
let (df, cf) = createChannel f
(dg, cg) = createChannel g
merge (First (CircuitChannel a r)) =
CircuitChannel (proc (e, (c, d)) -> do c' <- a -< (e, c)
d' <- dg -< d
returnA -< (c', d'))
r
merge (Second (CircuitChannel b r)) =
CircuitChannel (proc (e, (c, d)) -> do c' <- df -< c
d' <- b -< (e, d)
returnA -< (c', d'))
r
merge (Both (CircuitChannel a r) (CircuitChannel b _)) =
CircuitChannel (proc (e, (c, d)) -> do c' <- a -< (e, c)
d' <- b -< (e, d)
returnA -< (c', d'))
r
in (df <<< dg,
Map.map merge $
Map.unionWith (\(First x) (Second y) -> Both x y)
(Map.map First cf) (Map.map Second cf))
createChannel (CircuitChoice f g) =
let (df, cf) = createChannel f
(dg, cg) = createChannel g
merge (First (CircuitChannel a r)) =
CircuitChannel (proc (e, c) ->
case c of
Left x -> a -< (e, x)
Right x -> dg -< x) r
merge (Second (CircuitChannel a r)) =
CircuitChannel (proc (e, c) ->
case c of
Left x -> df -< x
Right x -> a -< (e, x)) r
merge (Both (CircuitChannel a r) (CircuitChannel b _)) =
CircuitChannel (proc (e, c) ->
case c of
Left x -> a -< (e, x)
Right x -> b -< (e, x)) r
in (df ||| dg,
Map.map merge $
Map.unionWith (\(First x) (Second y) -> Both x y)
(Map.map First cf) (Map.map Second cf))
createChannel (CircuitLoop f) =
let (df, cf) = createChannel f
in (loop df,
Map.map (\(CircuitChannel a r) ->
CircuitChannel (proc (e, a) -> do
rec (b, c) <- a -< (e, (a, c))
returnA -< b) r) cf)
I know that it will require some sort of type voodoo but where's error
now?
Regards
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part
Url : http://www.haskell.org/pipermail/haskell-cafe/attachments/20090903/8e99940a/attachment.bin
More information about the Haskell-Cafe
mailing list