0

I have defined my own type called CtrlV:

{-# LANGUAGE TemplateHaskell #-}
import Data.Data (Data, Typeable)
import Happstack.Server (Response, ServerPartT)
import Web.Routes (RouteT)
import Web.Routes.TH (derivePathInfo)

type App = ServerPartT IO
type CtrlV'   = RouteT Sitemap App
type CtrlV    = CtrlV' Response

data Sitemap   = Home | User
    deriving (Eq, Ord, Read, Show, Typeable, Data)
$(derivePathInfo ''Sitemap)

I have this function for example:

import Happstack.Foundation
import Happstack.Server (ok, toResponse)
import Web.Routes (showURL)
createResponse :: CtrlV
createResponse = do
     url <- showURL Home
     ok $ toResponse (show url)

I want to write a test for this function and i want to check Response has the correct result. But i can get Response out of my type CtrlV. Is there an easy way to achieve this?

alex.b
  • 184
  • 1
  • 2
  • 15
  • 5
    Well `CtrlV'` is *not a constructor. In fact it is a type synonym, so you are *not* wrapping any values. You have to use the same way as if you extract it out of a `RouteT Sitemap (ServerPartT IO) Response`. – Willem Van Onsem Aug 24 '18 at 12:02
  • If my reply is helpful to you, please accept it. – Samuel Barr Aug 24 '18 at 17:28
  • 1
    I keep saying that new users shouldn't use type synonyms. Does anyone listen? No, because new users never hear me say that. I'm preaching to the choir and screaming into the void. I wish there were some more efficient way to communicate. – dfeuer Aug 25 '18 at 01:23

1 Answers1

2

To step back from the specifics of the libraries your using, here is how type works:

I can declare a type synonym

type ListOfInts = [Int]

I know I can use ListOfInts anywhere I would use [Int]:

f :: ListOfInts -> Int
f xs = sum xs

g :: [Int] -> Int
g xs = product xs

list1 :: [Int]
list1 = [1,2,3]

list2 :: ListOfInts
list2 = [4,5,6]

f list1
> 6
f list2
> 15

g list1
> 6
g list2
> 120

And now I can use f and g on both list1 and list2, despite the fact that they are declared with "different" types. Type just declares a synonym for a type, not a new type (which would use the newtype keyword).

In summary, You can use CtrlV the same way you would use Ctrlv' Response, which you can use the same way you would use RouteT SiteMap App Response, which you can use the same way you would use RouteT SiteMap (ServerPartT IO) Response, because Ctrlv is RouteT SiteMap (ServerPartT IO) Response.

Samuel Barr
  • 434
  • 4
  • 12
  • Thanks for you answer. Is there a generic way to get values out of types? `RouteT` has the function `unRouteT :: (url -> [(Text, Maybe Text)] -> Text) -> m a` which seems to do what I want, but I don't understand how it works – alex.b Aug 26 '18 at 10:09
  • When you make a type synonym (which is what the type keyword does), you’re not creating a different type, you’re just creating a different way to refer to that type. So at the value level of the program, referring to the type using the actual name or a synonym makes no difference. – Samuel Barr Aug 26 '18 at 17:45