Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Example of function definition in the data constructor of a new type

We can use type synonym for function definitions, e.g.

type FuncDef = Int -> Int -> Int

This avoids us writing long function definition every time.

Use:

someFunc :: FuncDef -> Int

Instead of

someFunc :: (Int -> Int -> Int) -> Int

which is more readable and less code as well.

Simple algebraic data types are straight forward and easy to do pattern matching etc, e.g.

data AType = X | Y | Z Int
matchType :: AType -> Bool
matchType X = ..
matchType Y = ..
matchType (Z _) = ..

As I look more into Haskell data types, I found we can have function definition in data constructor when defining new type.

data MyType a b = X | Y (a -> b)

This puzzles me a bit and haven't seen many examples of this around. In a way, the idea of high-order function where a function can take another function as argument is similar to this situation, except here it applies to data type. The Haskell wiki does not say much about "high-order data type definition". I realise I may be getting all these terms wrong, so please correct me, and point me to more reading. I really want to see a concrete usage of this. Thanks!

matchMyType :: (MyType a b) -> Bool
matchMyType X = ..
matchMyType Y ?? = .. 
like image 587
vis Avatar asked Dec 14 '11 16:12

vis


2 Answers

You might use this kind of pattern in many situations. For example, if you want a function that transforms strings in various ways, you might have a data type like this (This is just an example that demonstrates the principle - don't write code like this!):

data StringTransformation =
  -- | Doesn't transform the string at all
  NoTransformation |
  -- | Takes the string and generates a suffix that should be appended
  Append (String -> String) |
  -- | Takes the string and generates a prefix that should be prepended
  Prepend (String -> String) |
  -- | Takes the string and transforms it arbitrarily to a new string
  Map (String -> String)

Then, a program that uses this might look like:

-- | Returns 'True' if the name is male
isMaleName :: String -> Bool
isMaleName = ...

-- | Adds a title to a name, for example "John Smith" -> "Mr. John Smith"
addTitle :: StringTransformation
addTitle =
  PrependTransformation $ \ name ->
  if isMaleName name
  then "Mr. "
  else "Mrs. "

-- Applies a string transformation to a 'String'.
transformString :: StringTransformation -> String -> String
transformString NoTransformation str = str
transformString (Append f) str       = str ++ f str
transformString (Prepend f) str      = f str ++ str
transformString (Map f) str          = f str
like image 168
dflemstr Avatar answered Oct 10 '22 21:10

dflemstr


data Thingy a b = A b
                | B (a -> b)

really :: Thingy a b -> a -> b
really (A x) _ = x              -- x :: b
really (B f) y = f y            -- f :: a -> b, y :: a, f y :: b

As C.A.McCann says, there's nothing special about functions really.

like image 35
dave4420 Avatar answered Oct 10 '22 23:10

dave4420