Skip to content

Instantly share code, notes, and snippets.

@viercc
Created February 23, 2024 06:53
Show Gist options
  • Save viercc/41094c695ad794220e4dbad1a63decb6 to your computer and use it in GitHub Desktop.
Save viercc/41094c695ad794220e4dbad1a63decb6 to your computer and use it in GitHub Desktop.
-- https://twitter.com/mi12cp/status/1753203763211571656
-- https://twitter.com/rsk0315_h4x/status/1753233137629646938
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ExistentialQuantification #-}
module Main where
import Data.IORef
-- trait Fn()
class Callable a where
call :: a -> IO ()
-- struct Foo<F>(Option<Box<F>>)
data Foo a = MkFoo (IORef (Maybe a))
hello :: Callable a => Foo a -> IO ()
hello _ = putStrLn "Hello!"
set :: Callable a => Foo a -> a -> IO ()
set (MkFoo ref) a = writeIORef ref (Just a)
run :: Callable a => Foo a -> IO ()
run (MkFoo ref) = readIORef ref >>= \ma -> case ma of
Nothing -> putStrLn "Nothing is set"
Just a -> call a
-- (|| foo.hello() ) : ?
-- ///
-- CallHello foo :: CallHelloClosure a
data CallHelloClosure a = Callable a => CallHello (Foo a)
instance Callable (CallHelloClosure a) where
call (CallHello foo) = hello foo
main :: IO ()
main = do
foo <- MkFoo <$> newIORef Nothing
run foo
set foo (CallHello foo)
-- ^^^^^^^^^^^^^
{-
• Couldn't match type ‘a0’ with ‘CallHelloClosure a0’
Expected: Foo a0
Actual: Foo (CallHelloClosure a0)
-}
run foo
-- Quantifying away 'a' works here, but the type system of Rust somehow
-- forbids "forgetting" the type of captured objects from the closure, I guess?
data CallHelloClosure' = forall a. Callable a => CallHello' (Foo a)
instance Callable CallHelloClosure' where
call (CallHello' foo) = hello foo
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment