Created
February 23, 2024 06:53
-
-
Save viercc/41094c695ad794220e4dbad1a63decb6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- 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