Could you explain a bit the scope of Frank? I will be glad to join but I'd like to understand what is the goal first.

The picture I had in my head was:

  • Microsoft WEB API is almost OK
  • Except routing seems to be a terrible hack
  • Most needed is nice typed F# API for defining web apps and services, compiling to basic non-routing WEB API signature HttpRequestMessage -> Async<HttpResponseMessage>
  • OWIN should be able to host an app of HttpRequestMessage -> Async<HttpResponseMessage> type
  • WebSockets should somehow be in the picture

Is that about right? Or do you want to do more in Frank?

By on 3/14/2013 12:51 PM ()

You've pretty much nailed it. I don't know that I would agree that routing is "a terrible hack." I would just prefer a different mechanism to handle routing. Specifically, I would prefer something that allowed nesting routes via composition. I'd also like to see routes type checked, meaning I get rid of strings and can reference routes by type (e.g. discriminated union) from within the app.

By on 3/23/2013 10:54 AM ()

Hi Ryan,

I had a quick glance at the project. Looks like the basis is `Req ->
Async<Resp>` - I quite like that. One question about it though: when
you compose these things in a hierarchy, say, you put handler `h`
under `/foo`, how does that work? Constructing a modified `Req`
object?

I once worked a similar little on a prototype we called "weblets" at
IntelliFactory, will try to convince my coworkers to open-source that
since we simply do not have time to work on it a lot. For now, I'll
just throw some ideas out. Weblets example code looks like that:

[link:gist.github.com]

The idea was very ambitious, I now wonder whether these requirements
are too ambitious for practical use. We wanted:

1. Composition: build bigger parts from smaller parts hierarchically

2. No reflection by default, full control - using techniques similar
to those presented at
[link:t0yv0.blogspot.com]

3. Type-safety: the basic idea is that a controller has parts of the
form ('A -> Async<'B>), and in general 'B depends on 'A, so in the end
it is expressed as an interface where every member is either a method
of the form 'A -> Async<'B> or a property typed with another interface
of the same kind.

4. Duality - once you define your weblet over an IMyController, you
can construct typed servers by providing IMyController, but you also
can construct typed clients by giving a base URL and receiving an
IMyController instance. That obviously puts some burden on the user
defining the weblet, as well as a lot of stress on the whole design :)
You have to demonstrate appropriate bijections for all 'A ~ Req and 'B
~ Resp.

5. Type-safe linking. Different parts of your application should be
able to link to each other type-safely. This is now sort of a feature
of WebSharper sitelets and we wanted to see if we could keep that
(since weblets intend to replace sitelets eventually if successful).
Unfortunately this was quite a bit harder. In the prototype, I had the
user match every controller interface with 'A -> Async<'B> methods
with a union type over all 'A variants. Then you could use `link : 'A
-> string` to produce cross-links.

I'd be curious to know what you think about (a) duality and (b) safe
cross-linking. Are either or both of these ideas worth pursuing?

Thanks,

Anton

By on 3/14/2013 12:22 PM ()

[link:apistrap.codeplex.com] Looks to be pursuing the duality you mentioned above, in a manner of speaking.

By on 3/23/2013 12:54 PM ()

At a first glance looks pretty terrible, I'll skip reading it for now :)

By on 3/23/2013 2:04 PM ()

Weblets looks interesting. I think it's serving a different purpose than what I envision for Frank, though I could see something like weblets being implemented on top of Frank.

Most of your goals equate with mine, especially points 1-3 and 5. I think they are all worth pursuing. Your #2 is exactly what I'm trying to address in Frank with this recent update for routing. #3 is addressed in the inner definitions leading up to a

1
HttpRequestMessage -> Async<HttpResponseMessage>

#5 is still to come. I haven't come up with a very easy way to achieve this, so I've been putting it off. (I'll address Duality at the bottom.)

The primary difference is our target. I'm targeting HTTP, and you appear to be more specifically targeting HTML.

Composition in Frank

The composition model in Frank is currently twofold:

Build up "applications" through smaller, composable functions

This is the more mature bit, as I used it to flush out the type signature of

1
HttpRequestMessage -> Async<HttpResponseMessage>

Those types really have nothing to do with HTML and everything to do with HTTP. Of course, you should be able to easily create other functions to compose the content, which is what you seem to be doing with Weblets.

Nest "applications" within a URI hierarchy

This is the part I was previewing in my announcement. The composition in 1 only builds a tree of routes; it doesn't affect the internals of any other "application." However, the tree could potentially be used to generate links for navigation or other actions available from a given HTTP resource.

Duality

I agree this is a goal. However, I want to build this around media types as the shared understanding between the client and the server. I don't want to generate a client for the server, per se, unless the server exposes a hypermedia API (via links). In that case, the generated client would merely be a scaffold.

I don't think there's anything wrong with the RPC approach taken in WebSharper. The goal of Frank is different in many ways from that of WebSharper and Weblets in that it's goals are again HTTP composition and loosely coupled server/client.

Conclusion

I do think we could build a common infrastructure. I really like the strong types for HTTP in System.Net.Http. I would prefer they were records rather than mutable types, but I'll take them. Something similar for OWIN would also be nice. The header value types each have parsers, so it's possible to build your own request and response types and use those parsers to retrieve the values.

Do you think it worthwhile to extend upon a more solid HTTP foundation? I think it would make it easier to build apps in WebSharper if I could build a model for the media type and share that over the client and server. That would allow me to continue crafting my APIs by hand with type-safe access over all of HTTP.

By on 3/23/2013 11:27 AM ()

Couple of questions:

1. Can you clarify 'media types'? You mean content negotiation? Returning different response on the same URL depending on what the client says in the Accept header? How do you see doing this: "share that over the client and server"?

2. Hm, I wonder where did I mention HTML? Maybe just the part about producing links of type `string`. I think HTML or no, the ability to produce links with a guarantee they are not going to be 404 is very important.

I am mostly interested in type-safe linking and duality because it is a nice brain-teaser - not exactly trivial problem of how to define F# combinators to make this read "natural." If you take both of these things out, there is almost nothing left to do :) I mean, as a programmer I can then just program around the HttpRequestMessage -> Async<HttpResponseMessage> type and host that - at least that is my naive view at the moment.

I tried to read Frank code but I cannot quite figure it out. The controller/dispatcher part seems to be doing some Invoke-style routing, something I have a hunch is an evil ("the terrible hack" I referred to above). I might be proven wrong, but at this point I think a good solution will be type-safe and not use reflection at all.

With open-sourcing, I think we ended up agreeing with Adam that if I am going to spend any work time on Apache 2.0 open-source code, then this code should have IntelliFactory branding (IntelliFactory.* in namespace and assembly name) and a requirement to attribute credit when reusing - I think this is a pretty reasonable way to get some value back to the company, at least making the brand known. So this makes it hard to me to work on Frank.. But I am happy to discuss ideas of course.

I will try to improve and release Weblets some time. Also Haskell ecosystem might be worth a look, that community has a lot of talent and they HAVE to come up with purely functional, reflection-free designs, so they may have a good idea for type-safe linking and duality.

By on 3/23/2013 2:23 PM ()

Couple of questions:

1. Can you clarify 'media types'? You mean content negotiation? Returning different response on the same URL depending on what the client says in the Accept header? How do you see doing this: "share that over the client and server"?

I wasn't strictly thinking of conneg here. I was thinking of the media type definition, which would define the semantics of link relations, etc. HTML and Atom(Pub) are good examples of hyperlink-aware media types. XML and JSON are good examples of almost meaningless media types. I was thinking of the former, and even more specifically something more like collection/json or HAL. Of course, the real win would be in using custom, internal media types, those that typically start application/vnd.my-media-type.

2. Hm, I wonder where did I mention HTML? Maybe just the part about producing links of type `string`. I think HTML or no, the ability to produce links with a guarantee they are not going to be 404 is very important.

I was basing my comment on what I thought I was seeing in Weblets. I thought you were composing markup sections, similar to web parts in SharePoint.

I tried to read Frank code but I cannot quite figure it out. The controller/dispatcher part seems to be doing some Invoke-style routing, something I have a hunch is an evil ("the terrible hack" I referred to above). I might be proven wrong, but at this point I think a good solution will be type-safe and not use reflection at all.

Yeah, the implementation of the Web API stuff is pretty gnarly. Web API uses the same sort of internal structuring as MVC, so all those pieces are there to support the reflective approach. My goal was to support the extensions available for Web API while removing all the actual reflection. I was able to avoid some parts of the API, but I had to implement a lot of the interfaces or base classes. Ultimately, I want someone to be able to add the help page extension without realizing there is a difference in the Frank option. I should still add a lot of comments to help people unfamiliar with the Web API (or MVC) codebase(s).

With open-sourcing, I think we ended up agreeing with Adam that if I am going to spend any work time on Apache 2.0 open-source code, then this code should have IntelliFactory branding (IntelliFactory.* in namespace and assembly name) and a requirement to attribute credit when reusing - I think this is a pretty reasonable way to get some value back to the company, at least making the brand known. So this makes it hard to me to work on Frank.. But I am happy to discuss ideas of course.

I'm not married to the name in any way. I thought it clever as it originally derived inspiration from Ruby's Sinatra, but I've since moved far, far away from any Sinatra-like API. If you find it useful and could bake some of this into an IntelliFactory namespace, I will happily change the namespace and even the name. That said, I think it would need to remain a more foundational level; something to be built on or alongside.

I will try to improve and release Weblets some time. Also Haskell ecosystem might be worth a look, that community has a lot of talent and they HAVE to come up with purely functional, reflection-free designs, so they may have a good idea for type-safe linking and duality.

I was watching Yesod for a time. They have a lot of that. And I really like that design. I was trying to mimic some of that in Frack, but F# doesn't quite have the type system for it (on the server-side, at least).

By on 3/23/2013 7:27 PM ()

Thanks Ryan for the detailed response.

  • So I skimmed collection/json and HAL docs. I am not sure if I understand it. But there is one way in which this made sense to me: if this is about creating self-describing data structures distributed on the web (comprised of multiple documents), with URLs serving for pointers. If that is what it is about, I buy that idea. But it also can be quite complicated. I would not venture into this before I have a simple story for the simpler things
  • Looks like I totally failed to communicate it. Okay, let me publish some code, then we will be able to talk about it with some precision.
  • I actually like Frank as a name, so we could end up with IntelliFactory.Frank to make everyone happy :) We might not agree though on the direction where this would go.. Anyway, let me come back to this next weekend - looks like I will not have much time for this anyway in the coming week.
  • Great, I will read into Yesod. I heard about but never actually checked it out.
By on 3/24/2013 2:05 PM ()

Thanks Ryan for the detailed response.

You are most welcome!

if this is about creating self-describing data structures distributed on the web (comprised of multiple documents), with URLs serving for pointers. If that is what it is about, I buy that idea. But it also can be quite complicated. I would not venture into this before I have a simple story for the simpler things

Yes, that's the idea. It's certainly non-trivial. I'm not certain I want to venture down that path, but it would be a very compelling story from a business perspective.

Looks like I totally failed to communicate it. Okay, let me publish some code, then we will be able to talk about it with some precision.

Sorry I missed it. I'm looking forward to your next snippet.

I actually like Frank as a name, so we could end up with IntelliFactory.Frank to make everyone happy :) We might not agree though on the direction where this would go.. Anyway, let me come back to this next weekend - looks like I will not have much time for this anyway in the coming week.

That name works for me. You are right that we might have different directions. I'm so far building on top of System.Net.Http because it's the best set of types available for .NET, but there's certainly room for improvement within F# to support pattern matching, in particular.

Great, I will read into Yesod. I heard about but never actually checked it out.

I thought you actually pointed that out to me. I guess I happened upon it while following the path of iterators. Very cool to see FsMachines, btw. Not sure if that's a solid approach for F#, but great to see the port becoming available, early though it is.

By on 3/24/2013 7:22 PM ()
IntelliFactory Offices Copyright (c) 2011-2012 IntelliFactory. All rights reserved.
Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy
Built with WebSharper