-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

On Wed, Nov 26, 2008 at 5:03 PM, Gwern Branwen  wrote:
> setBufferContents doesn't seem to exist. At least, recursive grep
> can't find anything but setBuffer.

OK, so I found two ways to do this:

> setBufferContents :: (MonadEditor m) => String -> m BufferRef
> setBufferContents article = withEditor $ stringToNewBuffer "Ireader article" 
> (B.fromString article)

And there seems to be a function almost identical to
stringToNewBuffer, in Buffer/Misc.hs, 'newB :: BufferRef -> String ->
LB.ByteString -> FBuffer'. I assume the important thing there is it
doesn't return a BufferRef.

So, setting a buffer is solved. But reading the buffer isn't. Trying
to figure out 'newB' lead me to look at the definition of FBuffer,
which has the line:

>                , rawbuf :: !(BufferImpl syntax)

BufferImpl, in Yi/Buffer/Implementation.hs, has the line:

>         FBufferData { mem        :: !ByteRope          -- ^ buffer text

So, if I had a 'getCurrentBuffer :: FBuffer', then presumably I could
then do 'contents :: ByteRope; contents = mem (getBuffer)', and then
finally convert the ByteRope to String with a
'Data.ByteRope.toString'.

As it happens, i can't do getCurrentBuffer, it seems. The only
possibilities seem to involve an 'Editor' in the type signature, which
doesn't seem to be accessible in a YiM.

But there is a 'getBufferWithName :: String -> EditorM BufferRef', and
I can make the assumption that my ireader buffer has a fixed name. So
now I have my BufferRef. Great. Once we have a BufferRef, we need to
follow that BufferRef to the FBuffer it is actually referencing. We do
a search - 'grep -R BufferRef|grep FBuffer', and we turn up:
Buffer/Misc.hs:keyB :: FBuffer -> BufferRef
Buffer/Misc.hs:newB :: BufferRef -> String -> LB.ByteString -> FBuffer
Editor.hs:       ,buffers       :: !(M.Map BufferRef FBuffer)
Editor.hs:buffersA :: Accessor Editor (M.Map BufferRef FBuffer)
Editor.hs:insertBuffer :: FBuffer -> EditorM BufferRef
Editor.hs:findBuffer :: BufferRef -> EditorM (Maybe FBuffer)
Editor.hs:findBufferWith :: BufferRef -> Editor -> FBuffer

keyB is the wrong direction (we already have the BufferRef); newB is
likewise useless; buffers is a false hit; I've no idea what buffersA
does. insertBuffer is interesting, but not what we're looking for.
findBufferWith has a need for Editor, which isn't accessible. So we go
with findBuffer. A little type-checking later, and we wind up with:

> *Main> :T join $ liftM findBuffer $ getBufferWithName "Ireader article"
> join $ liftM findBuffer $ getBufferWithName "Ireader article" :: EditorM 
> (Maybe FBuffer)

So:

> getFbuffer :: EditorM FBuffer
> getFbuffer = liftM fromJust $ $ join $ liftM findBuffer $ getBufferWithName 
> "Ireader article"

Now to apply 'mem' and get my ByteRope....

Oops. mem is defined in Buffer/Implementation.hs. And
Implementation.hs is not public, and Buffer.hs does not export
FBufferData nor any queries on it. So we can't use it.

But I've been at this a while, and the only viable alternative looks
to be some hideous hack involving the Region operators (which do get
access to stuff in Implementation) - it'd probably involve creating a
region covering the entire buffer, and then I could call 'readRegionB
:: Region -> BufferM String'. So instead I'm just going to edit the
cabal and make Yi.Buffer.Implementation - and also Data.ByteRope, for
that matter - public and reinstall.

One compile later, I realize that not only is Implementation not
public, the BufferImpl export is hiding all the accessors. An edit and
another compile later...

But of course, FBuffer isn't actually a FBufferData. That would be too
easy. So, we track FBuffer down to Buffer/Misc.hs, and see:

>                 , rawbuf :: !(BufferImpl syntax)

There are no helpful comments here, but we already know BufferImpl is
where all the good stuff is, so we just toss in a rawbuf into our
getFbuffer definition...

Oh no!

*Main Data.Maybe Yi.Buffer.Misc> :T liftM (rawbuf . fromJust) $ join $
liftM (findBuffer) $ getBufferWithName "Ireader article"
:1:7:

   Cannot use record selector `rawbuf' as a function due to escaped
type variables
    Probable fix: use pattern-matching syntax instead

    In the first argument of `(.)', namely `rawbuf'

    In the first argument of `liftM', namely `(rawbuf . fromJust)'

    In the first argument of `($)', namely `liftM (rawbuf . fromJust)'

What the heck is all that? Dunno. I mean, presumably a
pattern-matching version would look like this:

> bar (FBuffer {rawbuf = a}) = a

No, that doesn't work either. Let's do one more stab - we can
pattern-match in case expressions too:

> bar a = case a of
>         FBuffer { rawbuf = x } ->  x

No dice.

/home/gwern/.yi/yi.hs:101:9:

    Inferred type is less polymorphic than expected

      Quantified type variable `syntax' escapes

    When checking an existential match that binds

        x :: BufferImpl syntax

    The pattern(s) have type(s): FBuffer

    The body has type: BufferImpl syntax

    In a case alternative: FBuffer {rawbuf = x} -> x

    In the expression: case a of { FBuffer {rawbuf = x} -> x }


At around here, I give up and go to #haskell, where povman tells me
that my initial attempt is wrong - I can't return just x. Rather some
existential thing-a-ma-bobies mean that I have to immediately do
something with that x, so the right definition is

> bar a = case a of
>         FBuffer { rawbuf = x } ->  toString $ mem x

But... there's always a catch. This actually returns a [Word8]. So we
chuck in a 'show' call. Let's give them more pleasant names:

> getBufferRef :: EditorM FBuffer
> getBufferRef = liftM fromJust $ join $ liftM findBuffer $ getBufferWithName 
> "Ireader article"

> getBufferContents :: FBuffer -> String
> getBufferContents a = case a of
>         FBuffer { rawbuf = x } ->  show $ toString $ mem x

> getBuffer :: EditorM String
> getBuffer = liftM getBufferContents getBufferRef

So presumably our actual invocation would be 'newarticle
saveAndNewArticle :: YiM ()
> saveAndNewArticle = do olddb                        let newarticle = liftM 
> getBufferContents getBufferRef
>                       let newdb = liftM (updateSetLast olddb) newarticle
>                       liftM writeDB newdb
>                       let nextarticle = liftM getLatestArticle newdb
>                       liftM setBufferContents nextarticle
>                       return ()

But this is rife with all sorts of strange monad issues that are
driving me crazy and I just can't get past them. I've spent something
like 5 or 6 hours today going through Yi and trying stuff again and
again and it has driven me nuts and it has left me with chattering
teeth and bloody scalp.

We really need to make this stuff easier. I vote that we start by
adding some basic primitives like a getCurrentBuffer :: YiM String...

- --
gwern
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEAREKAAYFAkkuBEkACgkQvpDo5Pfl1oJ+kwCeIak9tOc/TDqLlk8z+5lYjcqY
zzgAoJAMCm7a4soMiScZA/Ut7VQOJ3ha
=aLKm
-----END PGP SIGNATURE-----

--~--~---------~--~----~------------~-------~--~----~
Yi development mailing list
yi-devel@googlegroups.com
http://groups.google.com/group/yi-devel
-~----------~----~----~----~------~----~------~--~---

Reply via email to