]> gitweb @ CieloNegro.org - Lucu.git/commitdiff
New module: Data.Eq.Indirect providing Eq' type class.
authorPHO <pho@cielonegro.org>
Thu, 22 Dec 2011 13:30:34 +0000 (22:30 +0900)
committerPHO <pho@cielonegro.org>
Thu, 22 Dec 2011 13:30:34 +0000 (22:30 +0900)
Ditz-issue: e6ec5a54d14cad8f79c456e23e92770fbbd3577e

Data/Eq/Indirect.hs [new file with mode: 0644]
Lucu.cabal
Network/HTTP/Lucu/DefaultPage.hs
Network/HTTP/Lucu/Postprocess.hs
Network/HTTP/Lucu/Resource.hs
Network/HTTP/Lucu/Response.hs
Network/HTTP/Lucu/StatusCode/Internal.hs

diff --git a/Data/Eq/Indirect.hs b/Data/Eq/Indirect.hs
new file mode 100644 (file)
index 0000000..a7aa8d1
--- /dev/null
@@ -0,0 +1,50 @@
+{-# LANGUAGE
+    FlexibleContexts
+  , TypeFamilies
+  , UnicodeSyntax
+  #-}
+-- |FIXME: doc
+module Data.Eq.Indirect
+    ( Eq'(..)
+    , (==:)
+    , (/=:)
+    , (≡:)
+    , (≢:)
+    , (≠:)
+    )
+    where
+import Prelude.Unicode
+
+infix 4 ==:{-, /=:, ≡:, ≢:, ≠:-}
+
+-- |FIXME: doc
+class Eq (Unified α) ⇒ Eq' α where
+    -- |FIXME: doc
+    type Unified α
+    -- |FIXME: doc
+    unify ∷ α → Unified α
+
+-- |FIXME: doc
+(==:) ∷ (Eq' α, Eq' β, Unified α ~ Unified β) ⇒ α → β → Bool
+{-# INLINE (==:) #-}
+(==:) = (∘ unify) ∘ (≡) ∘ unify
+
+-- |FIXME: doc
+(/=:) ∷ (Eq' α, Eq' β, Unified α ~ Unified β) ⇒ α → β → Bool
+{-# INLINE (/=:) #-}
+(/=:) = ((¬) ∘) ∘ (==:)
+
+-- |FIXME: doc
+(≡:) ∷ (Eq' α, Eq' β, Unified α ~ Unified β) ⇒ α → β → Bool
+{-# INLINE CONLIKE (≡:) #-}
+(≡:) = (==:)
+
+-- |FIXME: doc
+(≢:) ∷ (Eq' α, Eq' β, Unified α ~ Unified β) ⇒ α → β → Bool
+{-# INLINE CONLIKE (≢:) #-}
+(≢:) = (/=:)
+
+-- |FIXME: doc
+(≠:) ∷ (Eq' α, Eq' β, Unified α ~ Unified β) ⇒ α → β → Bool
+{-# INLINE CONLIKE (≠:) #-}
+(≠:) = (/=:)
index d07f14f29f20df625c9c226d2a5b9b0f6ae29e37..c6dfa354ad0f334d0e8d503a6aa410d0beb1eddb 100644 (file)
@@ -88,6 +88,7 @@ Library
             -DHAVE_SSL
 
     Exposed-Modules:
+        Data.Eq.Indirect
         Data.Collections.Newtype.TH
         Network.HTTP.Lucu
         Network.HTTP.Lucu.Abortion
index c5ae6f5c5d485ea8dbe4ca6046e70cbd7258ce47..a54bd590163a0f5d1dfe3804d05d548a860562f6 100644 (file)
@@ -16,6 +16,7 @@ import Data.Ascii (Ascii)
 import qualified Data.CaseInsensitive as CI
 import Data.Convertible.Base
 import Data.Convertible.Utils
+import Data.Eq.Indirect
 import Data.Maybe
 import Data.Monoid.Unicode
 import Data.Text (Text)
@@ -65,28 +66,28 @@ defaultMessage req res@(Response {..})
     -- 1xx responses don't have a body.
     -- 2xx responses don't need a body to be completed.
     -- 3xx:
-    | resStatus â\89\88 MovedPermanently
+    | resStatus â\89¡: MovedPermanently
         = do unsafeByteString "The resource at "
              path
              unsafeByteString " has been moved to "
              a ! href (toValue loc) $ toHtml loc
              unsafeByteString " permanently."
 
-    | resStatus â\89\88 Found
+    | resStatus â\89¡: Found
         = do unsafeByteString "The resource at "
              path
              unsafeByteString " is currently located at "
              a ! href (toValue loc) $ toHtml loc
              unsafeByteString ". This is not a permanent relocation."
 
-    | resStatus â\89\88 SeeOther
+    | resStatus â\89¡: SeeOther
         = do unsafeByteString "The resource at "
              path
              unsafeByteString " can be found at "
              a ! href (toValue loc) $ toHtml loc
              unsafeByteString "."
 
-    | resStatus â\89\88 TemporaryRedirect
+    | resStatus â\89¡: TemporaryRedirect
         = do unsafeByteString "The resource at "
              path
              unsafeByteString " is temporarily located at "
@@ -94,31 +95,31 @@ defaultMessage req res@(Response {..})
              unsafeByteString "."
 
       -- 4xx:
-    | resStatus â\89\88 BadRequest
+    | resStatus â\89¡: BadRequest
         = unsafeByteString "The server could not understand the request you sent."
-    | resStatus â\89\88 Unauthorized
+    | resStatus â\89¡: Unauthorized
         = unsafeByteString "You need a valid authentication to access " ⊕ path
-    | resStatus â\89\88 Forbidden
+    | resStatus â\89¡: Forbidden
         = unsafeByteString "You don't have permission to access " ⊕ path
-    | resStatus â\89\88 NotFound
+    | resStatus â\89¡: NotFound
         = do unsafeByteString "The requested URL "
              path
              unsafeByteString " was not found on this server."
-    | resStatus â\89\88 Gone
+    | resStatus â\89¡: Gone
         = do unsafeByteString "The resource at "
              path
              unsafeByteString " was here in past times, but has gone permanently."
-    | resStatus â\89\88 RequestEntityTooLarge
+    | resStatus â\89¡: RequestEntityTooLarge
         = do unsafeByteString "The request entity you sent for "
              path
              unsafeByteString " was too large to accept."
-    | resStatus â\89\88 RequestURITooLarge
+    | resStatus â\89¡: RequestURITooLarge
         = unsafeByteString "The request URI you sent was too large to accept."
 
       -- 5xx:
-    | resStatus â\89\88 InternalServerError
+    | resStatus â\89¡: InternalServerError
         = unsafeByteString "An internal server error has occured during the process of your request to " ⊕ path
-    | resStatus â\89\88 ServiceUnavailable
+    | resStatus â\89¡: ServiceUnavailable
         = unsafeByteString "The service is temporarily unavailable. Try later."
 
     | otherwise
index 7157b7d56e9dd14c4dcaa635ce47be599d2d15f6..c3aec8ec7fa2f54deea73257d63cc743c72497f2 100644 (file)
@@ -14,6 +14,7 @@ import Control.Monad
 import Control.Monad.Unicode
 import Data.Ascii (Ascii, CIAscii, AsciiBuilder)
 import Data.Convertible.Base
+import Data.Eq.Indirect
 import Data.Maybe
 import Data.Monoid.Unicode
 import GHC.Conc (unsafeIOToSTM)
@@ -47,16 +48,16 @@ abortOnCertainConditions (NI {..})
                    $ cs ("Inappropriate status code for a response: " ∷ Ascii)
                    ⊕ cs resStatus
 
-               when ( resStatus â\89\88 MethodNotAllowed ∧
-                      hasHeader "Allow" res        )
+               when ( resStatus â\89¡: MethodNotAllowed ∧
+                      (¬) (hasHeader "Allow" res)   )
                    $ abort'
                    $ cs ("The status was " ∷ Ascii)
                    ⊕ cs resStatus
                    ⊕ cs (" but no \"Allow\" header." ∷ Ascii)
 
-               when ( resStatus â\89\89 NotModified  ∧
-                      isRedirection resStatus  ∧
-                      hasHeader "Location" res )
+               when ( resStatus â\89¢: NotModified       ∧
+                      isRedirection resStatus        
+                      (¬) (hasHeader "Location" res) )
                    $ abort'
                    $ cs ("The status code was " ∷ Ascii)
                    ⊕ cs resStatus
index 1abf14be8e6bc7782d47e97bb3ddda75128b8c3b..fad0a62f4c541413f768144c3755bb5350390862 100644 (file)
@@ -159,6 +159,7 @@ import Data.Convertible.Base
 import Data.Convertible.Instances.Text ()
 import Data.Convertible.Utils
 import Data.Default
+import Data.Eq.Indirect
 import Data.List (intersperse, sort)
 import Data.Maybe
 import Data.Monoid
@@ -624,7 +625,7 @@ getForm limit
 -- 'isRedirection' or it raises an error.
 redirect ∷ StatusCode sc ⇒ sc → URI → Rsrc ()
 redirect sc uri
-    = do when (sc â\89\88 NotModified ∨ (¬) (isRedirection sc))
+    = do when (sc â\89¡: NotModified ∨ (¬) (isRedirection sc))
              $ abort
              $ mkAbortion' InternalServerError
              $ cs
index 1ff9ae71c51904dd87f427921527dd35d92fe014..f318fcf7ca7a9cb9a0b2ec7d14ec166ab54d9a84 100644 (file)
@@ -21,8 +21,6 @@ module Network.HTTP.Lucu.Response
     , setStatusCode
     , resCanHaveBody
 
-    , (≈)
-    , (≉)
     , isInformational
     , isSuccessful
     , isRedirection
@@ -35,6 +33,7 @@ import Data.Ascii (Ascii, AsciiBuilder)
 import Data.Convertible.Base
 import Data.Convertible.Instances.Ascii ()
 import Data.Convertible.Utils
+import Data.Eq.Indirect
 import Data.Monoid.Unicode
 import Network.HTTP.Lucu.Headers
 import Network.HTTP.Lucu.HttpVersion
@@ -92,9 +91,9 @@ resCanHaveBody ∷ Response → Bool
 {-# INLINEABLE resCanHaveBody #-}
 resCanHaveBody (Response {..})
     | isInformational resStatus = False
-    | resStatus â\89\88 NoContent     = False
-    | resStatus â\89\88 ResetContent  = False
-    | resStatus â\89\88 NotModified   = False
+    | resStatus â\89¡: NoContent    = False
+    | resStatus â\89¡: ResetContent = False
+    | resStatus â\89¡: NotModified  = False
     | otherwise                 = True
 
 -- |@'isInformational' sc@ returns 'True' iff @sc '<' 200@.
index e3122da1f55e21af4587abf5cf7d4175e8ccdd93..ec06f3e6b609c0fdfae10fdd36a5b9c6399cde33 100644 (file)
@@ -4,6 +4,7 @@
   , MultiParamTypeClasses
   , OverlappingInstances
   , TemplateHaskell
+  , TypeFamilies
   , UndecidableInstances
   , UnicodeSyntax
   , ViewPatterns
@@ -12,8 +13,6 @@
 module Network.HTTP.Lucu.StatusCode.Internal
     ( StatusCode(..)
     , SomeStatusCode
-    , (≈)
-    , (≉)
     , statusCodes
     )
     where
@@ -26,6 +25,7 @@ import qualified Data.ByteString.Lazy.Char8 as Lazy
 import Data.Convertible.Base
 import Data.Convertible.Instances.Ascii ()
 import Data.Convertible.Utils
+import Data.Eq.Indirect
 import Data.List
 import Language.Haskell.TH.Lib
 import Language.Haskell.TH.Syntax
@@ -39,7 +39,7 @@ import Prelude.Unicode
 -- 'statusCodes' quasi-quoter.
 --
 -- Minimal complete definition: 'numericCode' and 'textualStatus'.
-class Show sc ⇒ StatusCode sc where
+class (Eq sc, Show sc) ⇒ StatusCode sc where
     -- |Return the 3-digit integer for this status e.g. @200@
     numericCode ∷ sc → Int
     -- |Return the combination of 3-digit integer and reason phrase
@@ -49,32 +49,24 @@ class Show sc ⇒ StatusCode sc where
     fromStatusCode ∷ sc → SomeStatusCode
     fromStatusCode = SomeStatusCode
 
-instance StatusCode sc ⇒ Eq sc where
-    (==) = (≈)
+-- |Equivalence of 'StatusCode's. Two 'StatusCode's @a@ and @b@ are
+-- said to be equivalent iff @'numericCode' a '==' 'numericCode' b@.
+instance StatusCode sc ⇒ Eq' sc where
+    type Unified sc = Int
+    {-# INLINE CONLIKE unify #-}
+    unify = numericCode
 
 -- |Container type for the 'StatusCode' type class.
 data SomeStatusCode
     = ∀sc. StatusCode sc ⇒ SomeStatusCode sc
 
+instance Eq SomeStatusCode where
+    {-# INLINE CONLIKE (==) #-}
+    (==) = (≡:)
+
 instance Show SomeStatusCode where
     show (SomeStatusCode sc) = show sc
 
-infix 4 ≈, ≉
--- |Equivalence of 'StatusCode's. Two 'StatusCode's @a@ and @b@ are
--- said to be equivalent iff @'numericCode' a '==' 'numericCode' b@.
---
--- U+2248, ALMOST EQUAL TO
-(≈) ∷ (StatusCode α, StatusCode β) ⇒ α → β → Bool
-{-# INLINE (≈) #-}
-α ≈ β = numericCode α ≡ numericCode β
-
--- |@(a &#x2249; b) '==' 'not' (a &#x2248; b)@
---
--- U+2249, NOT ALMOST EQUAL TO
-(≉) ∷ (StatusCode α, StatusCode β) ⇒ α → β → Bool
-{-# INLINE (≉) #-}
-(≉) = ((¬) ∘) ∘ (≈)
-
 instance StatusCode SomeStatusCode where
     numericCode   (SomeStatusCode sc) = numericCode   sc
     textualStatus (SomeStatusCode sc) = textualStatus sc
@@ -111,17 +103,17 @@ instance StatusCode sc ⇒ ConvertAttempt sc AsciiBuilder where
 -- becomes:
 --
 -- @
---   data OK = OK deriving ('Show')
+--   data OK = OK deriving ('Eq', 'Show')
 --   instance OK where
 --     'numericCode'   _ = 200
 --     'textualStatus' _ = 'cs' (\"200 OK\" ∷ Ascii)
 --
---   data BadRequest = BadRequest deriving ('Show')
+--   data BadRequest = BadRequest deriving ('Eq', 'Show')
 --   instance BadRequest where
 --     'numericCode'   _ = 400
 --     'textualStatus' _ = 'cs' (\"400 Bad Request\" ∷ Ascii)
 --
---   data MethodNotAllowed = MethodNotAllowed deriving ('Show')
+--   data MethodNotAllowed = MethodNotAllowed deriving ('Eq', 'Show')
 --   instance MethodNotAllowed where
 --     'numericCode'   _ = 405
 --     'textualStatus' _ = 'cs' (\"405 Method Not Allowed\" ∷ Ascii)
@@ -179,7 +171,7 @@ statusDecl (num, phrase)
       name = mkName $ concatMap cs phrase
 
       dataDecl ∷ Q Dec
-      dataDecl = dataD (cxt []) name [] [con] [''Show]
+      dataDecl = dataD (cxt []) name [] [con] [''Eq, ''Show]
 
       instanceDecl ∷ Q [Dec]
       instanceDecl