Using ClassyPrelude to handle either Text or ByteString

Ok, I can't seem to figure out how to make this work, and since I'm using ClassyPrelude (from classy-prelude, latest version on hackage as of yesterday), I think cafe is a better place to ask than beginners. Sorry if this should have gone there. I want to read in a list of files, concatenate them, and then run the resulting data through a "process" function. So far, no problem. Given an opts record that contains the list of files and some control for the process function, this expression works: hPut stdout =<< process opts . concat <$> mapM (readFile . fpFromString) (files opts) (BTW, recommendations on cleaning that up gratefully accepted) However, I'd like to be able to read them all as either Text or ByteString, depending on options being passed to me. This doesn't work so well. If I give process a type of Text -> Text or ByteString->ByteString, everything works fine with no other changes. However, any attempt to make it polymorphic fails with ambiguous type warnings. I've tried a slew of things, and found a few that work. But none of them are what I'd call good, much less elegant. Is there a good way to do this?

First, we can clean that code:
do xs <- mapM (readFile . fpFromString) (files opts)
hPut stdout (process opts (concat xs))
You won't be able to make the decision of which type process should work
at inside of process because this decision will also affect which
implementation of readFile is used.
What you will need to do is inspect the 'opts' in the function above
and execute it at a type as determined by the options.
example opts
| isTextMode opts = aboveFunctionAsText opts
| isByteStringMode opts = aboveFunctionAsByteString opts
If you'd like to unify these into a single implementation as above
you'll need to provide some kind of extra information to resolve
the type ambiguity. This would have a type like:
aboveFunctionWithProxy :: IsSequence a => proxy a -> Options -> IO ()
exampleUsingProxies opts
| isTextMode opts = aboveFunctionWithProxy (Proxy :: Proxy Text)
opts
| isByteStringMode opts = aboveFunctionWithProxy (Proxy :: Proxy
ByteString) opts
The proxy parameter could then need to be linked to the type of the
internal xs parameter above using either scoped type variables or
a helper function similar to 'asTypeOf' with with a different type!
On Fri, May 8, 2015 at 1:10 PM, Mike Meyer
Ok, I can't seem to figure out how to make this work, and since I'm using ClassyPrelude (from classy-prelude, latest version on hackage as of yesterday), I think cafe is a better place to ask than beginners. Sorry if this should have gone there.
I want to read in a list of files, concatenate them, and then run the resulting data through a "process" function. So far, no problem. Given an opts record that contains the list of files and some control for the process function, this expression works:
hPut stdout =<< process opts . concat <$> mapM (readFile . fpFromString) (files opts)
(BTW, recommendations on cleaning that up gratefully accepted)
However, I'd like to be able to read them all as either Text or ByteString, depending on options being passed to me. This doesn't work so well. If I give process a type of Text -> Text or ByteString->ByteString, everything works fine with no other changes. However, any attempt to make it polymorphic fails with ambiguous type warnings.
I've tried a slew of things, and found a few that work. But none of them are what I'd call good, much less elegant. Is there a good way to do this?
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Eric Mertens
participants (2)
-
Eric Mertens
-
Mike Meyer