Michael Snoyman | 21 Apr 18:56
Favicon
Gravatar

Simple mime-type package

Hi all,


In Yesod, I have very modest needs when it comes to mime-types. Basically, I want:

* a data type to represent mime-types
* convert a string to a mime-type
* convert a mime-type to a string
* determine mime-type of a file based on extension

I've stuck all this in a simple module: Web.Mime[1]. However, it seems like this is a perfect candidate for a dedicated package. So I wanted to ask:

1) Is there a package out there- with minimal dependencies- that supplies this functionality?
2) If not, would anyone else find it useful if I split this off into its own package?

Michael

_______________________________________________
web-devel mailing list
web-devel@...
http://www.haskell.org/mailman/listinfo/web-devel
Jeremy Shaw | 22 Apr 18:42
Gravatar

Re: Simple mime-type package

Hello,

I am not especially excited about it. The fact that some mime-types are hard coded, and others are not is an annoying 'inconsistency'. 

There is no way to extend the list of supported types in user apps. And typeByExt has a rather limited set up extensions, declaring everything else to be application/octet-stream.

The use of a type for the mime-types implies that you want to be pattern matching on the constructors in your code ? Can you give a use case for that ?

- jeremy

On Apr 21, 2010, at 11:56 AM, Michael Snoyman wrote:

Hi all,

In Yesod, I have very modest needs when it comes to mime-types. Basically, I want:

* a data type to represent mime-types
* convert a string to a mime-type
* convert a mime-type to a string
* determine mime-type of a file based on extension

I've stuck all this in a simple module: Web.Mime[1]. However, it seems like this is a perfect candidate for a dedicated package. So I wanted to ask:

1) Is there a package out there- with minimal dependencies- that supplies this functionality?
2) If not, would anyone else find it useful if I split this off into its own package?

Michael

_______________________________________________
web-devel mailing list
web-devel-HC+Z4NTRIlBAfugRpC6u6w@public.gmane.org
http://www.haskell.org/mailman/listinfo/web-devel

_______________________________________________
web-devel mailing list
web-devel@...
http://www.haskell.org/mailman/listinfo/web-devel
Peter Robinson | 22 Apr 21:31
Picon

Re: Simple mime-type package

To avoid the hard coding issue, why not simply introduce a MimeType type class?

  Peter

On 22 April 2010 18:42, Jeremy Shaw <jeremy@...> wrote:
> Hello,
> I am not especially excited about it. The fact that some mime-types are hard
> coded, and others are not is an annoying 'inconsistency'.
> There is no way to extend the list of supported types in user apps. And
> typeByExt has a rather limited set up extensions, declaring everything else
> to be application/octet-stream.
> The use of a type for the mime-types implies that you want to be pattern
> matching on the constructors in your code ? Can you give a use case for that
> ?
> - jeremy
> On Apr 21, 2010, at 11:56 AM, Michael Snoyman wrote:
>
> Hi all,
> In Yesod, I have very modest needs when it comes to mime-types. Basically, I
> want:
> * a data type to represent mime-types
> * convert a string to a mime-type
> * convert a mime-type to a string
> * determine mime-type of a file based on extension
> I've stuck all this in a simple module: Web.Mime[1]. However, it seems like
> this is a perfect candidate for a dedicated package. So I wanted to ask:
> 1) Is there a package out there- with minimal dependencies- that supplies
> this functionality?
> 2) If not, would anyone else find it useful if I split this off into its own
> package?
> Michael
> [1] http://github.com/snoyberg/yesod/blob/ver0.2/Web/Mime.hs
> _______________________________________________
> web-devel mailing list
> web-devel@...
> http://www.haskell.org/mailman/listinfo/web-devel
>
>
> _______________________________________________
> web-devel mailing list
> web-devel@...
> http://www.haskell.org/mailman/listinfo/web-devel
>
>
Jeremy Shaw | 22 Apr 21:55
Gravatar

Re: Simple mime-type package


On Apr 22, 2010, at 2:31 PM, Peter Robinson wrote:

> To avoid the hard coding issue, why not simply introduce a MimeType  
> type class?

What would this class do ?

  - jeremy
Peter Robinson | 23 Apr 10:26
Picon

Re: Simple mime-type package

On 22 April 2010 21:55, Jeremy Shaw <jeremy@...> wrote:
> On Apr 22, 2010, at 2:31 PM, Peter Robinson wrote:
>> To avoid the hard coding issue, why not simply introduce a MimeType type
>> class?
>
> What would this class do ?

If extensibility is the main concern, then something like:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DeriveDataTypeable #-}
module Mime
where

import Data.Typeable
import Data.Convertible.Text

class ContentType t where
    typeByExt :: String -> t
    toString  :: t -> String

instance ContentType t => ConvertSuccess t [Char] where
  convertSuccess = toString

data TypeHtml = TypeHtml
  deriving(Typeable)

instance ContentType TypeHtml where
    typeByExt "html" = TypeHtml
    toString TypeHtml = "text/html; charset=utf-8"

-- Peter
Michael Snoyman | 23 Apr 13:44
Favicon
Gravatar

Re: Simple mime-type package



On Thu, Apr 22, 2010 at 9:42 AM, Jeremy Shaw <jeremy <at> n-heptane.com> wrote:
Hello,

I am not especially excited about it. The fact that some mime-types are hard coded, and others are not is an annoying 'inconsistency'. 

There is no way to extend the list of supported types in user apps. And typeByExt has a rather limited set up extensions, declaring everything else to be application/octet-stream.

The use of a type for the mime-types implies that you want to be pattern matching on the constructors in your code ? Can you give a use case for that ?


I wouldn't say that type implies pattern matching. I think the type makes code much clearer. For example, in Haskell I have:

type ChooseRep = [ContentType] -> IO (ContentType, Content)

I find that to be *much* clearer than

type ChooseRep = [String] -> IO (String, Content)

You could argue that I should just be using a type instead of a datatype, but that's an old debate between convenience and compiler type-safety. You could also argue that this should just be

newtype ContentType = ContentType String

I find three advantages for the current method. First, in theory passing around a TypeHtml constructor takes less memory than a ContentType "text/html; charset=utf-8", but I could be missing something about optimizations here. Second, it's just a lot more convenient to write in the first place. The alternative to having TypeHtml etc constructors would be:

typeHtml :: ContentType
typeHtml = ContentType "text/html; charset=utf-8"

Plus adding each function to the export list is just more tedious. Finally, I find the code *looks* better using a constructor than a function, eg

chooseRep [TypeHtml, TypeJson]

versus

chooseRep [typeHtml, typeJson]

though that's just a matter of taste.

I'm also not too concerned about the inconsistency, though I see where you're coming from. One of the advantages I'd see of opening this into a standalone package is that in theory the whole community could keep adding mimetypes until this is very comprehensive.

I find your argument to be more apropos to the typeByExt function, since that *is* a case where users would want to both extend and override library defaults. I see two options here:

* Change typeByExt to have return type "Maybe ContentType", and then users won't need to worry about the TypeOctet appearing all over the place. They can choose whatever default they want. If they want to extend or override, they just need to write their own function to be called before typeByExt.
* Don't provide a function at all; instead, provide a Map (or trie) with a number of built-in extension -> mimetype mappings. Users could then just do a lookup, as well as make changes to that Map.

Michael
_______________________________________________
web-devel mailing list
web-devel@...
http://www.haskell.org/mailman/listinfo/web-devel

Gmane