List of showables: OOP beats Haskell?

后端 未结 8 1277
无人及你
无人及你 2020-12-24 06:46

I want to build a list of different things which have one property in common, namely, they could be turned into string. The object-oriented approach is straightforward: defi

8条回答
  •  离开以前
    2020-12-24 07:16

    I would do something like this:

    newtype Strings = Strings { getStrings :: [String] }
    
    newtype DiffList a = DiffList { getDiffList :: [a] -> [a] }
    
    instance Monoid (DiffList a) where
        mempty                          = DiffList id
        DiffList f `mappend` DiffList g = DiffList (f . g)
    
    class ShowList a where
        showList' :: DiffList String -> a
    
    instance ShowList Strings where
        showList' (DiffList xs) = Strings (xs [])
    
    instance (Show a, ShowList b) => ShowList (a -> b) where
        showList' xs x = showList' $ xs `mappend` DiffList (show x :)
    
    showList = showList' mempty
    

    Now, you can create a ShowList as follows:

    myShowList = showList 1 "blah" 3.14
    

    You can get back a list of strings using getStrings as follows:

    myStrings = getStrings myShowList
    

    Here's what's happening:

    1. A value of the type ShowList a => a could be:

      1. Either a list of strings wrapped in a Strings newtype wrapper.
      2. Or a function from an instance of Show to an instance of ShowList.
    2. This means that the function showList is a variadic argument function which takes an arbitrary number of printable values and eventually returns a list of strings wrapped in a Strings newtype wrapper.

    3. You can eventually call getStrings on a value of the type ShowList a => a to get the final result. In addition, you don't need to do any explicit type coercion yourself.

    Advantages:

    1. You can add new elements to your list whenever you want.
    2. The syntax is succinct. You don't have to manually add show in front of every element.
    3. It doesn't make use of any language extensions. Hence, it works in Haskell 98 too.
    4. You get the best of both worlds, type safety and a great syntax.
    5. Using difference lists, you can construct the result in linear time.

    For more information on functions with variadic arguments, read the answer to the following question:

    How does Haskell printf work?

提交回复
热议问题