vacationlabs / haskell-webapps

Proof-of-concept code for a typical webapp implemented in various Haskell libraries/frameworks
MIT License
134 stars 21 forks source link

How to get Active/Inactive data constructors without prefixes? #1

Open saurabhnanda opened 8 years ago

saurabhnanda commented 8 years ago

Possible to remove the Tenant and User prefixes from the following without loss of type-safety?

data TenantStatus = TenantActive | TenantInactive
data UserStatus = UserActive | UserInactive | UserBlocked
mpickering commented 8 years ago
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}

data StatusType = User | Tenant

data Status (a :: StatusType) where
    Active :: Status a
    Inactive :: Status a
    Blocked :: Status User

type UserStatus = Status 'User
type TenantStatus = Status 'Tenant
saurabhnanda commented 8 years ago

@mpickering is it possible to extend this to the following:

data TenantStatus = TenantActive | TenantInactive
data UserStatus = UserActive | UserInactive | UserBlocked
data CustomerStatus = CustomerActive | CustomerBlocked
BartAdv commented 8 years ago

Aren't they gonna live in separate namespaces anyway?

saurabhnanda commented 8 years ago

@mpickering I'm not sure if I was clear earlier. Basically, the GADT-based solution that you proposed, works well if each data-model (User, Tenant, or Customer) has the same set of statuses. That might not always be the case, which is what I was trying to explain with the following:

data TenantStatus = TenantActive | TenantInactive -- doesn't have Blocked state
data UserStatus = UserActive | UserInactive | UserBlocked -- has all three state
data CustomerStatus = CustomerActive | CustomerBlocked -- doesn't have inactive state

@BartAdv not necessarily. Wouldn't it be easier to have a single module that defines all these types?

BartAdv commented 8 years ago

@saurabhnanda Yep, putting some types in common module seems to be widely accepted approach. But you just hit its limitation - after all, your problem is purely name resolution problem, right? Therefore, I think, the GADT trick would be overkill for that - you'd be fixing some language aspect by tossing some more advanced feature at it.

saurabhnanda commented 8 years ago

@BartAdv yes, you're right. But the question is slightly rhetorical in nature. Shouldn't it be easier to do stuff like this in Haskell?

The other purpose of this question is to discover any type-extension that makes this possible.

BartAdv commented 8 years ago

Well, maybe it should be easier. But Haskell isn't know for its powerful name resolution - after all, records remained main complaint the user had for some time.

I also don't think it's the issue of types being not expressive enough in this case (unless you want to write code that's polymorphic and you want to handle all XXXInactive statuses etc), that's why I wouldn't personally pursuit it.

saurabhnanda commented 8 years ago

unless you want to write code that's polymorphic and you want to handle all XXXInactive statuses etc

Not completely sure what you mean by this. Possible to share some code?

BartAdv commented 8 years ago

To be honest I'm not knowledgeable enough to know/prepare quick example of what could you potentially do with such an encoding - all I wanted to say is that only if you would need it for certain correctness guarantees, would it be worthy to explore.

sudhirvkumar commented 8 years ago

Just my 2 cents!

@saurabhnanda we can have these data declared in different NameSpaces and if we do then we might have to alias the module when we import T.Active T.Inactive

I understand that TenantActive and TenantInactive isn't as clean as Active and Inactive. But I believe we will get use to it?

Like I mentioned in my email and phone conversation. I am embracing Haskell and going with it.