Short note on Data.Proxy based on this Stackoverflow answer.

First, a few imports:

```
> {-# LANGUAGE RankNTypes #-}
> {-# LANGUAGE ScopedTypeVariables #-}
>
> module Proxy where
>
> import Data.Proxy
> import Text.Read
```

Suppose we want to check if some fuzzy real world data can be read as certain concrete types. We could write a few helper functions using readMaybe:

```
> readableAsInt :: String -> Bool
> readableAsInt s
> = case readMaybe s of
> Just (_ :: Int) -> True
> _ -> False
>
> readableAsDouble :: String -> Bool
> readableAsDouble s
> = case readMaybe s of
> Just (_ :: Double) -> True
> _ -> False
>
> readableAsBool :: String -> Bool
> readableAsBool s
> = case readMaybe s of
> Just (_ :: Bool) -> True
> _ -> False
```

These are all basically the same. How to generalise? Let’s try a typeclass.

```
> class ReadableAs t where
> readableAs :: String -> Bool
```

This doesn’t work since `readableAs`

doesn’t depend on the type `t`

:

The class method ‘readableAs’ mentions none of the type or kind variables of the class ‘ReadableAs t’ When checking the class method: readableAs :: String -> Bool In the class declaration for ‘ReadableAs’ Failed, modules loaded: none.

So put the type in:

```
> class ReadableAs' t where
> readableAs' :: t -> String -> Bool
```

This compiles, so let’s write some instances:

```
> instance ReadableAs' Int where
> readableAs' _ s
> = case readMaybe s of
> Just (_ :: Int) -> True
> _ -> False
>
> instance ReadableAs' Double where
> readableAs' _ s
> = case readMaybe s of
> Just (_ :: Double) -> True
> _ -> False
>
> instance ReadableAs' Bool where
> readableAs' _ s
> = case readMaybe s of
> Just (_ :: Bool) -> True
> _ -> False
```

Using it is clunky since we have to come up with a concrete value for the first argument:

> readableAs' (0::Int) "0" True > readableAs' (0::Double) "0" True

For some types we could use Data.Default for this placeholder value. But for other types nothing will make sense. How do we choose a default value for `Foo`

?

```
> data Foo = Cat | Dog
```

Haskell has non-strict evaluation so we can use `undefined`

, but, ugh. Bad idea.

> readableAs' (undefined::Int) "0" True

So let’s try out `Proxy`

. It has a single constructor and a free type variable that we can set:

> :t Proxy Proxy :: Proxy t

> Proxy :: Proxy Bool Proxy > Proxy :: Proxy Int Proxy > Proxy :: Proxy Double Proxy

Let’s use `Proxy t`

instead of `t`

:

```
> class ReadableAsP t where
> readableAsP :: Proxy t -> String -> Bool
>
> instance ReadableAsP Int where
> readableAsP _ s
> = case readMaybe s of
> Just (_ :: Int) -> True
> _ -> False
>
> instance ReadableAsP Double where
> readableAsP _ s
> = case readMaybe s of
> Just (_ :: Double) -> True
> _ -> False
>
> instance ReadableAsP Bool where
> readableAsP _ s
> = case readMaybe s of
> Just (_ :: Bool) -> True
> _ -> False
```

This works, and we don’t have to come up with the unused concrete value:

> readableAsP (Proxy :: Proxy Bool) "0" False > readableAsP (Proxy :: Proxy Bool) "True" True > readableAsP (Proxy :: Proxy Int) "0" True > readableAsP (Proxy :: Proxy Double) "0" True > readableAsP (Proxy :: Proxy Double) "0.0" True

Still, there’s a lot of duplication in the class and instances. We can do away with the class entirely. With the `ScopedTypeVariables `

language extension and the `forall`

, the `t`

in the type signature can be referred to in the body:

```
> readableAs :: forall t. Read t => Proxy t -> String -> Bool
> readableAs _ s
> = case readMaybe s of
> Just (_ :: t) -> True
> _ -> False
```

> readableAs (Proxy :: Proxy Int) "0" True > readableAs (Proxy :: Proxy Int) "foo" False