Skip to content

stepcut/safe-length

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Are you sick and tired of accidentally applying length to a tuple and getting back 1 instead of a compilation error? Does it make you feel like giving up on Haskell?

At last, there is a solution -- safeLength. For zero easy payments of 0 dollars and 00 cents, you can get the type safety you long for!

Before, if you accidentally wrote:

main :: IO ()
main = print $ length ('a', 'b')

you would get:

*Main> main
1

But with the new and improved safeLength you can rest easy. If you write:

main :: IO ()
main = print $ safeLength (Proxy :: Proxy [Char]) ('a', 'b')

You now get the glorious error:

*Main> :load example/Tuple.hs
[1 of 2] Compiling Data.Length      ( src/Data/Length.hs, interpreted )
[2 of 2] Compiling Main             ( example/Tuple.hs, interpreted )

example/Tuple.hs:7:51:
    Couldn't match type ‘(,) Char’ with ‘[]’
    Expected type: [Char]
      Actual type: (Char, Char)
    In the second argument of ‘safeLength’, namely ‘('a', 'b')’
    In the second argument of ‘($)’, namely
      ‘safeLength (Proxy :: Proxy [Char]) ('a', 'b')’
    In the expression:
      print $ safeLength (Proxy :: Proxy [Char]) ('a', 'b')
Failed, modules loaded: Data.Length.

"But wait!", you say. "I want to take the length of a tuple." No problem! safeLength can do that too!

main :: IO ()
main = print $ safeLength (Proxy :: Proxy (Char, Char)) ('a', 'b')

As desired, we get 1:

*Main> main
1

But that's not all! What if you have nested lists and you accidentally take the length of the wrong list. For example, what if you want the length of the outer list, but you accidentally write:

import GHC.OldList as OldList

main :: IO ()
main = print $ OldList.length (head [['a','b','c']])

Oh the horror! It compiles and we get:

*Main> main
3

And that is even using the old monomorphic, length :: [a] -> Int!!

But with safeLength all is well! If we accidentally write:

main :: IO ()
main = print $ safeLength (Proxy :: Proxy [[Char]]) (head [['a', 'b', 'c']])

We get not 1, not 2, but 3 type errors

*Main> :load example/NestedList.hs
[1 of 2] Compiling Data.Length      ( src/Data/Length.hs, interpreted )
[2 of 2] Compiling Main             ( example/NestedList.hs, interpreted )

example/NestedList.hs:7:61:
    Couldn't match expected type ‘[Char]’ with actual type ‘Char’
    In the expression: 'a'
    In the expression: ['a', 'b', 'c']
    In the first argument of ‘head’, namely ‘[['a', 'b', 'c']]’

example/NestedList.hs:7:66:
    Couldn't match expected type ‘[Char]’ with actual type ‘Char’
    In the expression: 'b'
    In the expression: ['a', 'b', 'c']
    In the first argument of ‘head’, namely ‘[['a', 'b', 'c']]’

example/NestedList.hs:7:71:
    Couldn't match expected type ‘[Char]’ with actual type ‘Char’
    In the expression: 'c'
    In the expression: ['a', 'b', 'c']
    In the first argument of ‘head’, namely ‘[['a', 'b', 'c']]’
Failed, modules loaded: Data.Length.

That's right! 3 type errors for the low, low price of $0.00.

Act now and we'll throw in these unit tests at no additional cost! Don't delay! Hackage servers are standing by!

About

Tired of accidentally calling length on tuples? Relief at last!

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published