<div dir="ltr">I don't think you understood me, maybe I wasn't clear enough but what I meant was that the ref was identical if and only if the enum seed is identical. (enumToIORef 5, enumToIORef 5) consists of two identical references. The enumToIORef function is completely reverentially transparent and its order of execution should not matter. (enumToIORef 5) :: Defaultable a => IORef a should always return the same ref. It will return a different ref however for each type a. In this sense, the hypothetical program:<div><br></div><div>x = enumToIORef 0;</div><div><br></div><div>y = enumToIORef 0;</div><div><br></div><div>main = do {</div><div>  writeIORef x "Hello, World"; -- writes to ref x</div><div>  message <- readIORef y; -- reads from ref y, which is identical</div><div>  putStrLn message;</div><div>};</div><div><br></div><div>Should output "Hello, World\n"</div><div><br></div><div>However, as noted by Roman, a subtle bug occurs in this case:</div><div><br></div><div><div>x = enumToIORef 0;</div><div><br></div><div>y = enumToIORef 0;</div><div><br></div><div>main = do {</div><div>  writeIORef x "Hello, World"; -- writes to ref x</div><div>  message <- readIORef y; -- reads from ref y, which is NOT identical</div><div>  print (message + 1);</div><div>};</div></div><div><br></div><div>In this case the compiler deduces (with monomorphic restriction) that (y :: IORef Int) while (x :: IORef String), as such since enumToIORef is asked to return two different types each time it returns two different references. message is in this case read from the default value of 0 and "1\n" is output. </div><div><br><div><div><br>On Sunday, 15 December 2013 14:00:17 UTC+1, Joe Quinn  wrote:<blockquote class="gmail_quote" style="margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
  
    
  
  <div bgcolor="#FFFFFF" text="#000000">
    <div>This has the same issue as just using a
      top-level (IORef b). Assume two use cases:<br>
      <br>
      let x = enumToIORef 5 in (x, x)<br>
      (enumToIORef 5, enumToIORef 5)<br>
      <br>
      It's "obvious" in the first case that you have one ref that is
      used twice, while it is "obvious" in the second case that you have
      two refs containing the same value. But this breaks the rule that
      (let x = y in f x) = (f y), because the left is a single ref while
      the right is two refs.<br>
      <br>
      There's likely other problems with it too, but this is what stands
      out to me.<br>
      <br>
      On 12/15/2013 6:39 AM, EatsKittens wrote:<br>
    </div>
    <blockquote type="cite">
      <div dir="ltr">
        <div>A pure function (enumToIORef :: (Enum a, Defaultable b)
          => a -> IORef b). This function returns referentially
          transparently an IORef as a function of its "seed" with the
          guarantee that the IORef returned is identical if and only if
          the seed is. This function can be used to implement top level
          mutable state in a module. The module can specifically create
          an enumerated type for this and not export it, thereby
          removing any possibility of another module passing the seed
          type and conflicting.</div>
        <div><br>
        </div>
        <div>The Defaultable class is added in this case to implement
          only a single method (defaultValue :: Defaultable a => a
          -> a). This is conceptionally the 'simplest' value of the
          type, such as the empty list, the number 0, False, the null
          character &c. The IORef returned by enumToIORef would be
          initialized before being written to to this specific default
          value of its type. This approach is chosen because it is
          impossible to initialize it to user specified value because
          enumToIORef can be called twice with the same seed but a
          different initial value.</div>
        <div><br>
        </div>
        <div>In the alternative it is also possible to do without the
          default value and say the IORef returned is the same if and
          only if the seed and the initial value given are the same.
          Allowing the function to remain referentially transparent as
          well. This would probably require for good semantics the
          underlying type of the IORef to be a member of EQ...?</div>
        <div><br>
        </div>
        <div>All this would of course require that newIORef and
          enumToIORef never produce the same IORef.</div>
        <div><br>
        </div>
        <div>Aside its limitations of the type IORef's initialized with
          this method can carry, I do believe they cover the vast
          majority of use cases of top level mutable state?</div>
        <div><br>
        </div>
        <div>Caveats?</div>
        <div><br>
        </div>
      </div>
      <br>
      <fieldset></fieldset>
      <br>
      <pre>______________________________<wbr>_________________
Haskell-Cafe mailing list
<a href="javascript:" target="_blank" gdf-obfuscated-mailto="ueAfV0kkp9AJ" onmousedown="this.href='javascript:';return true;" onclick="this.href='javascript:';return true;">Haskel...@haskell.org</a>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank" onmousedown="this.href='http://www.google.com/url?q\75http%3A%2F%2Fwww.haskell.org%2Fmailman%2Flistinfo%2Fhaskell-cafe\46sa\75D\46sntz\0751\46usg\75AFQjCNHiVycCM53czUVzPma4Fkb_wPqP2A';return true;" onclick="this.href='http://www.google.com/url?q\75http%3A%2F%2Fwww.haskell.org%2Fmailman%2Flistinfo%2Fhaskell-cafe\46sa\75D\46sntz\0751\46usg\75AFQjCNHiVycCM53czUVzPma4Fkb_wPqP2A';return true;">http://www.haskell.org/<wbr>mailman/listinfo/haskell-cafe</a>
</pre>
    </blockquote>
    <br>
  </div>

</blockquote></div></div></div></div>