Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8922037
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T06:43:38+00:00 2026-06-15T06:43:38+00:00

I’m torn between two implementations of a certain data structure, and input from the

  • 0

I’m torn between two implementations of a certain data structure, and input from the Haskell community as to what is right/standard would be appreciated.

Data Types

Take, for example, a ADT “Server” which defines several servers as nullary data constructors.

data Server = Server1
            | Server2
            | Server3

Now, for each of these servers I want to have (among other things) the ability to get an IP address. Assuming I can code these statically, I can have some function “getURL” and pattern match.

getUrl :: Server -> String
getUrl Server1 = "192.168.1.1"

and etc. Now any function which uses servers can put Server in the type and call getURL.

serverStuff :: Server -> IO ()

This method seems to have the benefit of simple, non-polymorphic functions at the expense of having lots of pattern matching in getURL. Additionally, if the programmer adds a Server but forgets to add the pattern to getURL, they will get a runtime error without warning unless they compile with -Wall.

Typeclasses

Attacking the same problem with typeclasses, I can break out my multi-constructor ADT into a set of ADTs specific to the server and create a type class for URL.

data Server1 = Server1
data Server2 = Server2
data Server3 = Server3

class Server a where
    getUrl :: a -> String

instance Server Server1 where
    getUrl Server1 = "192.168.1.1"

and etc. Now instead of the simple non-polymorphic function I used before, I have to create something like

serverStuff :: Server a => a -> IO ()

and deal with the implications of ad-hoc polymorphism (function specialization and the like).

On the bright side, the typeclass method easy to expand, breaks up the pattern matching into smaller chunks, allows for greater abstraction e.g. grouped servers (data ServerCenter1 = Server1 | Server2 | Server3), and, while you can still get runtime errors (without compiler warning) if you don’t declare getUrl, you’re at least forced to make that decision when you create the instance.

So, I’m torn but leaning toward instances as a better way of doing things. Is there a standard way to handle this issue, or is it a “whatever seems clean” type of thing?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T06:43:40+00:00Added an answer on June 15, 2026 at 6:43 am

    If you are positive that the only information you need your server type to contain, I would just implement them as a newtype around a string:

    newtype Server = Server { getURL :: String }
    

    Making it a full record (as in hammar’s comment) would allow you to add information while changing only the constructors, at the expense of GeneralizedNewtypeDeriving.

    In general, I would use types to represent classes of things and variables to represent particulars, so that nullary constructors are used only to represent abstracts, e.g. data Status = Published | Draft (or the builtin Bool). Hardcoding data (such as ip addresses) into the type system or functions should be avoided, unless there is a specific reason.


    If you want server specific behaviors, it is easy to add fields to the record:

    data Server = Server {
                  getURL      :: String
                , doSomething :: a -> IO () --Or any other functional signature
                }
    

    However, I would advise against doing this, because it makes other code obscure:

    runSomething :: Server -> a -> IO ()
    runSomething server arg = (doSomething server) arg
    

    can do absolutely anything, and you need to locate the last update of that field to determine what (since functions have no Show instance). If the dependency depends on some property of the server, I would favor encoding that property and then dispatching on that, e.g.

    data ServerType = Production
                    | Development
    
    data Server = Server {
                  getURL     :: String
                , serverType :: ServerType
                }
    
    runSomething :: Server -> a -> IO ()
    runSomething server arg = case serverType server of
                                  Production  -> foo arg
                                  Development -> bar arg
    

    I consider this approach superior to hardcoding server names into the function, because it explains why a given server has a given behavior (and makes changing the behavior of a particular server more local), and to having functions in the record fields, as it makes it easier to tell what a given invocation of runSomething will do (as one can inspect and log the ServerType).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I would like to run a str_replace or preg_replace which looks for certain words
I have a string like this: La Torre Eiffel paragonata all’Everest What PHP function
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I want to count how many characters a certain string has in PHP, but
For some reason, after submitting a string like this Jack’s Spindle from a text
this is what i have right now Drawing an RSS feed into the php,
I am currently running into a problem where an element is coming back from
I'm parsing an RSS feed that has an ’ in it. SimpleXML turns this
I would like to count the length of a string with PHP. The string
I've tracked down a weird MySQL problem to the two different ways I was

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.