paf31 / purescript-jquery

Type declarations for jQuery
MIT License
30 stars 28 forks source link

Control.Monad.JQuery.create too permissive? #21

Open AKST opened 9 years ago

AKST commented 9 years ago

Context

First off I'm not sure what the long term goal of this library is, whether it is to provide an API that mirrors JQuery's close as possible (if so this is all me), or it's suppose to raise the abstraction to one that better suits Purescript and it's typesystem. Either way thanks for the library. Secondly I'm just getting started with purescript and I figured I'd mention some struggles I had when first using this library.

My struggle

Anyways so when I first started with this library I just looked at the types, and in particular the type for create which is...

create :: forall eff. String -> Eff (dom :: DOM | eff) JQuery

Looks simple enough, except I hadn't realised that even though the function was called create, I still need to include angle brackets in the string you passed to it, for it to create a tag, so my chain of thought was to use the function like this

main = ready do
  heading <- J.create "h1" >>= J.setText "Hello World"
  appBody <- select "#app"
  J.append heading appBody

How it should have been written is like so

main = ready do
  heading <- J.create "<h1>" >>= J.setText "Hello World"
  appBody <- select "#app"
  J.append heading appBody

Function definition

But judging by the definition of the functions select & create it wouldn't have made difference if I had chosen either, as long as I formatted the string correctly

foreign import create
  """
  function create(html) {
    return function () {
      return jQuery(html);
    };
  }
  """ :: forall eff. String -> Eff (dom :: DOM | eff) JQuery
foreign import select
  """
  function select(selector) {
    return function () {
      return jQuery(selector);
    };
  }
  """ :: forall eff. String -> Eff (dom :: DOM | eff) JQuery

So what happened in my original example was I actually selected all the h1 tags on the page changed their text to "Hello world" and inserted them into $("#app"), but since I had no h1 tags on the page, my page remained blank.

Possible alternative type

Would if be worth while creating an abstract data type like this to used in the place of the string in create?

-- I'm not sure what purescript's equalivent of newtype 
-- is, but I'd write it like this in haskell
newtype TagName = TagName { getTagName :: String }

h1 = TagName "<h1>"
p = TagName "<p>"
a = TagName "<a>"
-- lots of boilerplate!!!

So the definition stays the same, and the type of the function becomes

create :: forall eff. TagName -> Eff (dom :: DOM | eff) JQuery

I guess the draw back with this is you can't throw in arbitrary html, like <p>Hello World</p> like you can do with JQuery. But the function is called create, so maybe that's the job of a completely different function?

Anyways, Obviously I've solved the problem for my original code, but I figured due to confusion I had first starting out with this library maybe it's worth modifying the API for other new comers? Either way thanks again for writing this library!