<div dir="ltr"><div><div><div><div><div><div>@Marlin  Thank you for the example.  Looks very interesting. Initially, when I was modelling this problem, I did consider Phanton types. But, you do provide a nice extension using type classes.<br><br></div>Here are the obstacles/discomfort I faced while I took the Phantom Polymorphism approach:<br><br></div>1.  With the definition of Basket c,  how do I create a  type such as <br><br></div> Cart = [Basket].  The only way to create such a cart is  Cart c = [Basket c]. But, that ties the Cart to one definition of Basket.  Is there a way around this? I might be missing something simple.<br><br></div>2.  In your approach or in the approach suggested by others, ultimately, I end up handling the 'Frozen' type during run-time. There is no way from stopping somene write code that calls update's on Frozen. (For example while mapping..).  Is that understanding correct?<br><br><br></div>Does this approach give me any more power than the previous approaches?  The one power is that we stop the user from being able to construct the Frozen type, and we leave it to the compiler to return that type based on the inference. Correct? Is there any other power.<br><br></div>Thank you for the help. Just with this thread, I have learnt more than 3 different ways of modelling approaches for this kind of  a problem!<br><div><div><div><br><br><br></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jul 31, 2016 at 11:41 AM, MarLinn via Haskell-Cafe <span dir="ltr"><<a href="mailto:haskell-cafe@haskell.org" target="_blank">haskell-cafe@haskell.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
  
    
  
  <div bgcolor="#FFFFFF" text="#000000">
    <p>This sounds like a perfect opportunity to use phantom types. I'll
      be using it's DataKind-enhanced variant for added beauty.</p><span class="">
    <blockquote type="cite">
      <div dir="ltr">--  An Item that can be of two types,  one whose
        value can be changed, one whose value are frozen once created  <br>
        data Item = FreeToChange {freeToChangeCount:: Int}<br>
          | CannotChange {frozenCount:: Int}<br>
      </div>
    </blockquote>
    </span><p>I assume all items are equal apart from their changeability. Not
      that it's necessary, but it makes the demonstration simpler. If
      changeable and unchangeable items have differing structure you may
      need additional tools like smart constructors. Accordingly, my
      items have the type</p>
    <pre>    data PlainItem = PlainItem { count :: Int }
</pre>
    <p>Changeability will be added on top:<br>
    </p>
    <pre>    data Changeability = Changeable | Unchangeable

    data Item (c :: Changeability) = Item { plainItem :: PlainItem }
</pre>
    <p>Why separate <i>Item</i> and <i>PlainItem</i>? One second,
      please.<br>
    </p><span class="">
    <blockquote type="cite">
      <div dir="ltr">-- The item is part of a basket<br>
        data Basket = Basket { name:: String, item::Item }<br>
      </div>
    </blockquote>
    </span><pre>    data Basket c = Basket { name :: String, item :: Item c }  -- No kind signature necessary. Thanks, solver.

</pre><span class="">
    <blockquote type="cite">
      <div dir="ltr">Therefore, valid operation are:<br>
        <br>
        1. I can create an Basket with either FreeToChange item or
        CannotChange item.<br>
      </div>
    </blockquote>
    <br></span>
    The new <i>Basket</i> constructor can do that by default.<span class=""><br>
    <br>
    <blockquote type="cite">
      <div dir="ltr">2. I can update the count for FreeToChange item in
        the Basket<br>
      </div>
    </blockquote>
    </span><pre>    changeItem :: (PlainItem -> PlainItem) -> Item 'Changeable -> Item 'Changeable</pre>
    <pre>    changeItem f (Item i) = Item (f i)</pre>
    <pre>    changeBasket :: (PlainItem -> PlainItem) -> Basket 'Changeable -> Basket 'Changeable</pre>
    <pre>    changeBasket f basket@Basket{..} = basket { item = changeItem f item }</pre>
    <br>
    And that's why <i>PlainItem</i> was separated, so we can have a
    simple type signature here. You might worry that it was exposed, but
    it will not give anyone access to a frozen basket. And of course you
    are free to further restrict access to it. And as we're speaking
    about freezing, that's extremely simple as well.<br>
    <pre>    freezeItem :: Item c -> Item 'Unchangeable</pre>
    <pre>    freezeItem (Item i) = Item i</pre>
    <pre>    freezeBasket :: Basket c -> Basket 'Unchangeable</pre>
    <pre>    freezeBasket basket@Basket{..} = basket { item = freezeItem item }

</pre>
    <p>You later mention that you might want to map updates only over
      some of the baskets in a cart. That's not hard either. As an
      example, here's a way to implement a function that updates
      changeable baskets while ignoring unchangeable ones:</p>
    <pre>    class MaybeUpdateBasket c where
        updateBasket :: (PlainItem -> PlainItem) -> Basket c -> Basket c
    instance MaybeUpdateBasket 'Changeable where
        updateBasket = changeBasket
    instance MaybeUpdateBasket 'Unchangeable where
        updateBasket _ = id
</pre>
    <p>Just <i>map</i> it over your cart as always.<br>
    </p>
    <p>If you want more complicated things (eg. you want a cart to
      freeze once any bucket freezes) you just have to expand the ideas
      here. You may need MultiParamTypeClasses and
      FunctionalDependencies, but the basic ideas are the same.</p>
    <p>Cheers.<br>
    </p>
    <pre></pre>
  </div>

<br>_______________________________________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
Only members subscribed via the mailman list are allowed to post.<br></blockquote></div><br></div>