# Looking for Assumptions in code¶

When writing functional code, a good general heuristic for making code more reusable is to remove assumptions. Examples adapted from ps unscripted on code reuse

Note

this section needs breaking down into smaller chunks, or to be simplified.

## Example¶

```
sayHello :: List String -> List String
sayHello Nil = Nil
sayHello (name : names) =
("Hello, " <> name) : sayHello names
```

Contains several assumptions. The first and most obvious is that we wish to say hello. We can move towards

```
prefixAll :: String -> List String -> List String
prefixAll prefix Nil = Nil
prefixAll prefix (first : rest) =
(prefix <> first) : prefixAll prefix rest
sayHello = prefixAll "Hello, "
```

This code now contains the assumption that the caller wants to prefix every item in a list. Instead

```
transform :: (String -> String) -> List String -> List String
transform f Nil = Nil
transform f (first : rest) =
(f first) : transform f rest
prefixAll prefix = transform (prefix <> _)
suffixAll suffix = transform (_ <> suffix)
```

We're assuming that the transformation has to happen on a String over a list of strings - this can easily be changed in just the type signature. No code changes need to happen to fit this idea in.

```
transform :: forall a. (a -> a) -> List a -> List a
```

But now we're assuming the starting type has to be the same as the resulting type - one more type-level change

```
transform :: forall a b. (a -> b) -> List a -> List b
```

This is looking pretty good now - but we're assuming the caller wants to use a `List`

...

```
transform :: forall f a b. (a -> b) -> f a -> f b
```

```
type Transform f a b = (a -> b) -> f a -> f b
transformList :: forall a b. Transform List a b
-- or even, because most callers will want to supply `f` but not `a b`
type Transform f = forall a b. (a -> b) -> f a -> f b
transformList :: Transform List
```

This lets us build all-sorts. We can still be polymorphic with the `f`

```
formatAll :: forall f. Transform f -> f Number -> f String
formatAll t = t number.toString
```

This lets us provide transforming functions to make even less assumptions

```
sayHello :: forall f. Transform f -> f String -> f String
sayHello transform names = transform ("Hello, " <> _)
```

Most languages would stop here - but purescript has Typeclasses. Instead of pulling our pattern out as a Type and having to pass fulfilment functions around, we can declare our pattern as a Typeclass

```
class Transform f where
transform :: forall a b. (a -> b) -> f a -> f b
instance transformList :: Transform List where
transform f Nil = Nil
transform f (x : xs) =
(f x) : transform f xs
formatAll :: forall f. Transform f => f Number -> f String
formatAll = transform number.toString
```

Transform here is a renamed `Functor`