Feeds:
Posts
Comments

Archive for the ‘Uncategorized’ Category

News and improvements

Hey everybody.

I am once more without day job, and so patch-tag is getting more attention than it is used to. Could patch-tag be a day job, after all? Let’s just say I am toying with this idea but trying to stay grounded too. I don’t have as many users as I wanted when I started this project — not by a long shot. However, a good proportion of the users I do have seem to be “real” users — actually using repos, browsing around, not just signing up and moseying away when the novelty wears off. This is good. On the other hand, I worry that the logs I am basing this on might not be fair — perhaps bots or other phenomena are responsible for the apparent signs of activity. So, this — understanding true usage — is also something I am working on.

This week was mostly incremental improvements, but it was all stuff that has to happen before shooting for bigger goals (gitit, git format repos, and todo lists).

  • Edit profile page improvements: you can change your primary email, delete profile, etc
  • The repo command page has a “push patches over email: ” section.
  • Added some admin functionality, for better understanding my user base, and in preparation to pull the trigger on paid repos at some time in the not too distant future
  • Refactored and cleaned up a lot of code. Hey, is that a feature? Maybe not for you… but it’s a feature for me, the guy that has to deal with self-created mess.

I am also working on a talk to evangelize happstack to the southern california FP and web dev community sometime in the next few weeks.

Stay cool, and keep tagging.

Read Full Post »

A wise haskell hacker said you don’t need to understand monads to use em, and this I find to be mostly true.

You don’t need to understand category theory either.

Lately though, I’ve been trying to deepen my intuition a bit anyway.

This is something I wrote lately that I keep revisiting when thinking about monadic machinery: specificaly the bind, left bind, join and return operators, as well as the pure and fmap operators used with Applicative and Functor.

How do these funny named operators fit together and what are they good for?

Concrete examples help, and for now my concrete example is the list monad. Pure and return do the same thing, since the list monad is also an applicative functor: just :[], put in a list. Fmap is, of course, map. I find myself using left bind more often than bind in my code, and in the list monad left bind is concatMap. Oh, and join is concat. You don’t hear about join much, but it turns out to be important when understanding monads categorically. Join takes m (m a) -> m (a), ie two monad nestings deep to one. Mysterious, eh?

If any of this rang a bell and you have been scratching your head for a simple bit of code you can stare at and play around with in your head, you may enjoy this.

To start with, try out f1 xs, f2 xs, f3 xs, u1 xs, u2 xs in ghci, just to see what’s giong on. Then… well, just read the code for suggestions about how to learn from it.

{-# LANGUAGE NoMonomorphismRestriction #-}
import Control.Applicative
import Control.Monad
import Test.QuickCheck

-- inspired by mixing monads, arrows, and applicative functors
-- http://yumagene.livejournal.com/2245.html
--  http://www.sfu.ca/~ylitus/courses/cmpt481731/slides/FPjul9.pdf

-- An interesting thing for learning you can do in your head:
-- replace (=<<), (<$>), and join with the list equivalents, after staring at this for a while.
-- The equivalents:
--   (=<<): concatMap
--   (<$>): map
--   join: concat
-- doing that helped me understand monad/functor machinery better.

-- a list of lists, to illustrate "burrowing in" two levels with (<$>) . (<$>) and other machinery
xs :: [[Integer]]
xs = [[2,4,6],[7..13],[10,20..50]] 

t = sequence_ [tflattened, tunflattened]

infs = repeat [1,2,3] -- the f functions produce output fine with infinite lists as well.

-- you lose the "list of lists" structure, because (=<<)/join are flattening
f1 els = (=<<) ((<$>) (* 3)) $ els
f2 els = join . ((<$>) $ (<$>) (* 3)) $ els
f3 els = join . (((<$>) . (<$>)) (*3)) $ els -- same thing, note the burrowing in two levels thing.
tflattened = quickCheck p
  where p :: [[Integer]] -> Bool
        p xs = (f1 xs) == (f2 xs) && (f1 xs) == (f3 xs)

-- if you want to preserve the list of lists structure, compose your monadic function with (pure .) behind it.
u1 els = (=<<) (pure . (<$>) (* 3)) els
u2 els = join . ((pure . (<$>) (* 3)) <$>) $ els

tunflattened = quickCheck p
  where p :: [[Integer]] -> Bool
        p xs = u1 xs == u2 xs


--flatten=join


-- Questions/Lessons Learned: 

-- Q0: are f1 and f2, and u1 and u2 the same function?
-- by same I mean
-- a) produce the same output for the same input everywhere (appears to be true for list monad)
-- b) computed the same way, one is not more efficient than the other
-- Answer to Q0: yes, pretty much.

-- Q1. what is the relationship between bind and join?
-- A. -- (=<<) f mx = join . (f <$>)  $ mx -- bind could have been defined this way, though in practice it's not.
  --  translation : -- functor map your monad function over the monad value (<$> f)
                    -- and pop one level of structure (join)
                    -- in a list, (=<<) f is concat . (map f)
-- Q. can this be proved using monad/functor/applicative laws or similar?
-- A. not proved exactly, but more like trivially true assuming the monad laws hold for your structure, which they should. 
--   (Monad laws should be proven separately for each structure you define a monad laws. They *are* proven for list, maybe, maybe others.
-- Q. does ((<$>) . (<$>)) have some interesting roles in reasoning about monads or applicatives?
-- A. Burrow in two levels before applying the function.


-- (=<<) is concatMap in list context. join is concat in list context.


Read Full Post »

Patch-Tag has upgraded to darc 2.3.1.

I have also started logging darcs actions to see which ones take the longest in hopes of providing the development cabal with intelligence for some hard to squash bugs.

Read Full Post »

Patch-Taggers, I am about to pull the trigger on namespaced repos.

That means that repo paths will look like

http://patch-tag.com/r/myuser/myrepo

rather than (current)

http://patch-tag.com/r/myrepo

This is nice if you want to branch someone else’s repo, no need to call it repo_vxxx or however people have been doing it.

This breaks public repo urls, however. After this feature goes live

http://patch-tag.com/r/myrepo

will give you a search of all repos created by any user which match that name.

Private repo urls checkouts *should* continue to work with a symlink, but if there is any problem please go to the repo home page and look at the

I expect this feature will go live sometime in the next few hours, and I will update again after I pull the trigger.

Update: Site is down while migration in progress.

Update: Site is up again. Looks like private repo url checkouts do not work with symlink as I had hoped. I’ll look into this tomorrow.

If anything else appears to not be working please email me or notify the patch-tag-users google group.

Thanks for your patience, and I hope you enjoy namespaces!

Read Full Post »

Hey taggers, I have stopped being a full time entrepreneur and got a job with a startup that pays the bills: scaling and automations engineer with modernfeed.com, which is being rebranded under a domain which I must not name, at least for the next six weeks.

Confession time: I have not done a lot for patch tag the last two months, other than think and answer emails. (Well, I did a few tweaks to gitit and filestore, which will hopefully pay off eventually here.)

Two months ago is when I decided, I Must Get Paid, and monetizing patch tag was going to take longer than I could wait. Month 1 (June) I spent mainly in new york trying to cobble together a startup that merited enough VC money to live on, with a team that could do it full time. I felt like a scrappy screenplay writer on the mean streets of hollywood (except this was new york) pitching to producer after producer, living in a basement while I reached for my dreams, wheeling and dealing… except that this didn’t have a hollywood ending… I just kind of lost steam and said, enh.

Month 2 (July) I spent hunting for a paying job, bouncing between chicago, san francisco and L.A.

Funny thing, now I actually DO work in hollywood!

Now that I am gainfully employed again, I hope that I will actually be able to start investing some energy into patch tag again, on nights and weekends.

From what I hear, the baby that has been keeping up the other half of the partnership may be approaching the end of the “cry all night” stage as well.

So, we shall see!

Read Full Post »

Patch-Taggers, there’s been a lot of action in our personal lives lately, some foreseen and some that just snuck up on us.

I will be pitching an idea that is kinda-sorta related to patch-tag, but not patch-tag itself, to a tech angel in nyc in a few days, so spending a lot of energy preparing for that.

Matt is expecting some major life changes as well, but I will let him speak for himself if he feels like it :)

Point is, we are putting what we can into the project and you can expect good things in the pipe, but bear with us a bit if it seems slow for the next week or so.

Specifically, the regression in diffs vis a vis gitit is being worked on, and username namespaced repos as well.

As always, we appreciate honest feedback from our growing band of merry users.

Cheers.

Read Full Post »

Holy freebies, batman, it’s May and we still haven’t started charging for private repos… Yep, it’s taking patch-tag longer to get the commercial ball rolling than planned. Hope nobody minds.

For now, matt and I are focused on improving usability and working out our payments functionality.

The biggest change is a new repo browser. Patch-tag no longer relies on gitit, though we are using a modified filestore module. How this came to be, and what it means for patch-tag users and pour future plans is a topic I hope to address in another blog post. The short and sweet is that I am a lot happier with the feel of repository browsing, and I think it was worth the work to switch from a pure open source community system.

In other news, swayed by recent developments in the darcs world, the ghc project has put their plans for switching from darcs to git indefinitely on hold.

http://hackage.haskell.org/trac/ghc/wiki/Status/May09

Git’s market is still 30X that of darcs according to google’s research tools, but definitely a shot in the arm for the “other” dvcs.

Read Full Post »

I just reinstalled ubuntu on my development laptop because the hard drive seems to have been hosed after a hard reboot. (Wubi is vulnerable to those.)

Everything was backed up on patch-tag, so no major drama.

One annoyance was the cabal install I ran for installing patch-tag was getting hung up on some dependency related to this issue

http://groups.google.com/group/fa.haskell/browse_thread/thread/3e556db4901e1db8?pli=1

only the advice in that thread didn’t help me, since the error I was getting was that

cabal: dependencies conflict: ghc-6.10.1 requires base ==4

uninstalling base seemed like a bad idea, and I knew that this installer had succeed elsewhere.

So, I sshed in to another box where the install had worked, and ran the following script to determine the *exact* package versions that patch-tag was using by doing

ghc-pkg field patch-tag depends

I specified the exact versions (== for every package dependency) in the cabal file in my new virgin environment, and the problem went away.

Shrug.

Hopefully this kind of annoyance will just go away as cabal keeps gettin the kinks worked out and the haskell platform begins a reality.

Read Full Post »

I just made my first patch to the darcs source, a minor fix correcting an incorrect help message that has always bugged me.

http://lists.osuosl.org/pipermail/darcs-users/2009-April/018914.html

Stuff I have learned:

There are two different build systems with darcs: cabal and make.

Cabal install does the usual thing

Make is what you want if you want to load darcs into ghci. You need to run autoconf first, which means you need autoconf installed — apt-get install autoconf on debuntu. Then just autoconf; configure; make ghci.

Beter to hack on darcs during daytime pacific time, when there are people on the #darcs channel to answer questions. It’s a lot of code to grok!

Read Full Post »

I was browsing the FileStore code and got to thinking that the FileStore data type rubbed me the wrong way because it hides IO, diluting the Purity of Essence of haskell’s precious type system.

In ghci of our code that uses FileStore:


:t darcsFileStore "/home/thartman/patchwiki/wikis/happstacktest/"
darcsFileStore "/home/thartman/patchwiki/wikis/happstacktest/" :: FileStore

I see that and I think, cool, a pure value.

Then I think — oops, wrong.


data FileStore
= FileStore {initialize :: IO (),
save :: forall a.
(Contents a) =>
ResourceName -> Author -> Description -> a -> IO (),
retrieve :: forall a.
(Contents a) =>
ResourceName -> Maybe RevisionId -> IO a,
delete :: ResourceName -> Author -> Description -> IO (),
rename :: ResourceName
-> ResourceName
-> Author
-> Description
-> IO (),
history :: [ResourceName] -> TimeRange -> IO [Revision],
latest :: ResourceName -> IO RevisionId,
revision :: RevisionId -> IO Revision,
index :: IO [ResourceName],
idsMatch :: RevisionId -> RevisionId -> Bool,
search :: SearchQuery -> IO [SearchMatch]}

Now I think, aha, this is OO in haskell.

So, what would I want instead?

First idea: how about something like


type FileStore = [resourceName] -- pure

and then a class of RepoAble or something like that which has a bunch of pure methods that must be implemented for any concrete instance of the class. (revision, latest, retrieve, history, index, idsMatch, search)
Then you would have some unavoidably impure methods like save, delete, rename.

Concrete instances could then be defined for Darcs, Git, Svn, etc. You basically have a nice wrapper over various types of repos.

On second thought though, maybe not such a good idea. To have everything work purely after an initial fetch, the FileStore value would have to contain everything in the repo. Nah.

I just want that darned FileStore value tagged with the IO type somehow so I can tell visually when looking at the code that we’re in impure land.

This is when I realized my mistake.

Since all the fields in FileStore are functions, there’s nothing impure about it after all. If one of the fields of fileStore had a concrete value related to a repo, this would smell wrong, because we’re mixing pure and impure — but that’s not the case here.

I think the confusion for me is that I am used to seeing “interfaces” in haskell defined in terms of implementation of a type class, but here the interface is just the arbitrary fields of a datatype, which I think is a bit less type safe.

So, I still think FileStore could be improved that way by taking advantage of typeclassing, but it’s not a matter of it being impure like I initially thought.

Read Full Post »

« Newer Posts - Older Posts »

Follow

Get every new post delivered to your Inbox.