[Haskell-cafe] An idea on extensible effects (anonymous record)

winter drkoster at qq.com
Tue Nov 22 14:14:41 UTC 2016


Hi MarLinn!

In my use case the type collision is definitely much less likely to happen, that is i often want to compose different effects like logger, sql and network ,etc. without Has class, i will have a hard time trying to compose `Reader Logger ()` and `Reader (Logger, HttpClient) ()`, since the concrete type can't be unified.

If i need two different Logger in environment, i still can do it without Tagged, i can define following newtypes in library site:

newtype StdLogger = StdLogger Logger
newtype FileLogger = FileLogger Logger

librarySite :: (Has StdLogger r, Has FileLogger r, MonadReader r m) => m ()
librarySite = do ...
                 stdLogger :: StdLogger <- asks get
                 logWith stdLogger
                 ...
                 fileLogger :: FileLogger <- asks get
                 logWith fileLogger
                 ...

And in application site i should supply a (StdLogger log1, FileLogger log2, ...).

Does above example illustrate my use case to you?

Cheers~
Winter



> On 22 Nov 2016, at 21:48, MarLinn <monkleyon at googlemail.com> wrote:
> 
>>>  Which brings us back to fclabels I suppose.
>> Can you elaborate this? I haven’t fully understand what is “incorporate the tag in the class from the start” . Thanks you.
> 
> Suppose you have the original definitions
> class Has a t where
>     get :: t -> a
> 
> instance Has a (a, b) where
>   get (a, _) = a
> 
> instance Has b (a, b) where
>   get (_, b) = b
> This creates a conflict if you use an (Int,Int) tuple because there are either no definitions or two conflicting definitions for get.
> As a solution you propose something along the lines of
> Has (Tagged “GetGetsFirst” a) (a,b)
>  All I'm saying is that it seems useful or even necessary for sanity to combine Has and Tagged so that you can write 
> Has “fst” a (a,b)
> The implementation should be something simple like
> class (KnownSymbol label) => Has label part whole | whole,label -> part where
>     get :: Proxy label -> whole -> part
> -- 'Proxy label' is necessary because 'whole' and 'part' alone are not sufficient to determine the label. See (Int,Int).
> The obvious downside is that it doesn't make as much sense to have such a class now. I must admit I'm not too familiar with the alternatives, so I can't really compare it. But this was just a flaw I saw. Hope this cleared up what I meant.
> 
> Cheers,
> MarLinn
> 
>>>>> Does this differ significantly from fclabels or the upcoming OverloadedRecordFields extension? (Aside from being purely type driven, which has problems in your example if you compose a second Int into it.)
>>>> 
>>>> 1. Yes, it’s similar to OverloadedRecordFields but doesn’t force you to use a label, and you may use Tagged to label a field if you want.
>>>> 2. Yes, but again, you can use Tagged to allow same type in different disguise.
>>> I can see a potential problem because you can't hide instances. Once you define a Has-relationship, you can't cheaply change it. That could lead to conflicts, unless you hack around it with orphaned instances in a separate module. But you say you want to solve conflicts with tagging – so it would be reasonable to incorporate the tag in the class from the start. Which brings us back to fclabels I suppose.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20161122/6eae6f02/attachment.html>


More information about the Haskell-Cafe mailing list