-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to have dynamic effects that take handles as arguments #17
Comments
Here's how I did it: data FsWeird es = MkFsWeird
{ readFileImpl :: forall ex sm. Exception String ex -> Stream Int sm -> FilePath -> Eff (sm :& ex :& es) String,
writeFileImpl :: FilePath -> String -> Eff es ()
}
instance Handle FsWeird where
mapHandle fs@MkFsWeird {readFileImpl, writeFileImpl} =
MkFsWeird
{ readFileImpl = \ex sm fp -> useImpl2 $ readFileImpl ex sm fp,
writeFileImpl = (fmap . fmap) useImpl writeFileImpl
}
readFile :: (e :> es, ex :> es, sm :> es) => Exception String ex -> Stream Int sm -> FsWeird e -> FilePath -> Eff es String
readFile ex sm MkFsWeird {readFileImpl} fp = subsume2L $ useImpl2 $ readFileImpl ex sm fp
writeFile :: (e :> es) => FileSystem e -> FilePath -> String -> Eff es ()
writeFile fs filepath contents = useImpl (fs.writeFileImpl filepath contents)
runFileSystemPure ::
(e0 :> es) =>
State Int e0 ->
[(FilePath, String)] ->
(forall e2. FsWeird e2 -> Eff (e2 :& es) r) ->
Eff es r
runFileSystemPure st fs0 k =
evalState fs0 $ \fs ->
useImplIn
k
MkFsWeird
{ readFileImpl = \ex sm filepath -> do
fs' <- get fs
yield sm 1
yield sm 1
put st 1
case lookup filepath fs' of
Nothing ->
throw ex ("File not found: " <> filepath)
Just s -> pure s,
writeFileImpl = \filepath contents ->
modify fs ((filepath, contents) :)
}
subsume2L :: (e1 :> es, e2 :> es) => Eff (e1 :& e2 :& es) a -> Eff es a
subsume2L = Unsafe.Coerce.unsafeCoerce
useImpl2 :: (e :> es) => Eff (e1 :& e2 :& e) a -> Eff (e1 :& e2 :& es) a
useImpl2 = Unsafe.Coerce.unsafeCoerce This seems like it makes interpretations easier while making call sites a little harder. |
Ah yes, that's also nice. I think it's more important to make interpretations easier, because they tend to be more complex and written more often. Call sites just need to fit a simple standard pattern, and they're only defined once. What we really need is one simple way of doing all the different forms of this problem. One good thing about your version is that it's compatible with @Lysxia's version. Perhaps we can combine the two and use that as the standard way. |
I'm pleased to say that
I'm not sure about |
By the way, I think the implementations of |
I managed to make this simpler. Turns out it's unnecessary to have separate effect types for each handle argument. No need for data FsWeird es = MkFsWeird
{ readFileImpl ::
forall e.
Exception String e ->
Stream Int e ->
FilePath ->
Eff (e :& es) String,
writeFileImpl ::
FilePath ->
String ->
Eff es ()
}
instance Handle FsWeird where
mapHandle MkFsWeird {readFileImpl, writeFileImpl} =
MkFsWeird
{ readFileImpl =
\ex sm fp -> insertManySecond (readFileImpl ex sm fp),
writeFileImpl =
\fp s -> useImpl (writeFileImpl fp s)
}
readFile ::
(e1 :> es, e2 :> es, e3 :> es) =>
Exception String e1 ->
Stream Int e2 ->
FsWeird e3 ->
FilePath ->
Eff es String
readFile ex sm MkFsWeird {readFileImpl} fp =
inContext (readFileImpl (mapHandle ex) (mapHandle sm) fp)
writeFile ::
(e :> es) => FsWeird e -> FilePath -> String -> Eff es ()
writeFile fs filepath contents =
useImpl (writeFileImpl fs filepath contents)
runFileSystemPure ::
(e1 :> es) =>
State Int e1 ->
[(FilePath, String)] ->
(forall e. FsWeird e -> Eff (e :& es) r) ->
Eff es r
runFileSystemPure st fs0 k =
evalState fs0 $ \fs ->
useImplIn
k
MkFsWeird
{ readFileImpl = \ex sm filepath -> do
fs' <- get fs
yield sm 1
yield sm 1
put st 1
case lookup filepath fs' of
Nothing ->
throw ex ("File not found: " <> filepath)
Just s -> pure s,
writeFileImpl = \filepath contents ->
modify fs ((filepath, contents) :)
} |
This ought to be resolved by: https://hackage.haskell.org/package/bluefin-0.0.11.0/docs/Bluefin-Compound.html#g:8. Please feel free to reopen if you think it's not resolved. |
As an example, suppose that we have a file system effect. We might want to be able to handle errors in the readFile function, but still have it be dynamically interpreted while using some other unknown effects. What we want is something similar to the incorrect code below.
The text was updated successfully, but these errors were encountered: