title: How to implement actions in ST-monad with my own underlying representation (similarly to STRef or STArray) using simple techniques?
body: <p>I want to manipulate structs of a certain type from FFI through an interface like that provided with <code>STArray</code> or <code>STRef</code> in an <code>ST</code> monad. I'll have my own specific methods with understandable names for the kind of manipulations that are useful for this struct (like <code>readArray</code> and <code>writeArray</code> for arrays).</p>
  
  <p>What is the simplest way to implement this?</p>
  
  <p>The implementation for <code>STArray</code> (based on <a href="https://hackage.haskell.org/package/base-4.7.0.2/docs/src/GHC-Arr.html" rel="noreferrer">https://hackage.haskell.org/package/base-4.7.0.2/docs/src/GHC-Arr.html</a>) looks too convoluted for those who do not know some special GHC techniques used for this.</p>
  
  <p>Can I write something on a more simple, understandable level of Haskell?</p>
  
  <h3>Remarks</h3>
  
  <p>I'm not asking about how to access a struct through FFI.</p>
  
  <p>I'd rather write getter and setter functions in C, and I want to mirror them in Haskell (to get ST-actions like <code>readArray</code> and <code>writeArray</code>).</p>
  
  <h3>Some thoughts on easy declaration of this kind of interface (a possible GHC extension?)</h3>
  
  <p>If I'm not mistaken, I can declare a foreign function as either an IO-action or pure (if I'm sure it is pure). I understand the latter as simply shortcutting wrapping it in <code>unsafePerformIO</code>:</p>
  
  <pre><code>foreign import ccall safe "getValue.h getValue" effect :: CInt -&gt; Ptr CChar
  foreign import ccall safe "getValue.h getValue" pure :: CInt -&gt; IO (Ptr CChar)
  </code></pre>
  
  <p>So, the idea arises that an <strong>intermediate form between "effect" and "pure"</strong> could be possible, to save programmer's work. An "effect" limited to a "limited state":</p>
  
  <pre><code>foreign import ccall safe "getValue.h writeValue" writeValue :: (ValueRef s) -&gt; Value -&gt; ST s () -- modeled after writeSTRef
  </code></pre>
  
  <p>in addition to the standard two variants for this function in GHC:</p>
  
  <pre><code>foreign import ccall safe "getValue.h writeValue" writeValue :: ValueRef -&gt; Value -&gt; IO ()
  foreign import ccall safe "getValue.h writeValue" writeValue :: ValueRef -&gt; Value -&gt; () -- must be really bad!
  </code></pre>
  
  <p>I only can't get the details about <code>ValueRef</code> right: if we define this unparameterized type, then how can the compiler use a parameterized one to give an ST-action?..</p>
  
  <p>Probably, this is not available in GHC, but could be useful extension, couldn't it?</p>