-- |
-- Module      : Test.LeanCheck.Function.Show.FourCases
-- Copyright   : (c) 2015-2020 Rudy Matela
-- License     : 3-Clause BSD  (see the file LICENSE)
-- Maintainer  : Rudy Matela <rudy@matela.com.br>
--
-- This module is part of LeanCheck,
-- a simple enumerative property-based testing library.
--
-- This module exports an orphan 'Show' instance for functions.
-- It shows functions as up to 4 case distinctions in a single line.
--
-- Please see "Test.LeanCheck.Function.Show.EightLines" for an alternative that
-- shows functions as up to 8 case distinctions, one per line.
--
-- The 'Show' '->' instance only works for functions of which ultimate return
-- types are instances of the 'ShowFunction' typeclass.  Please see
-- "Test.LeanCheck.Function.ShowFunction" for how to define these instances for
-- your user-defined algebraic datatypes.
--
-- Warning: this is only intended to be used in testing modules.  Avoid
-- importing this on modules that are used as libraries.
module Test.LeanCheck.Function.Show.FourCases () where

import Test.LeanCheck.Function.ShowFunction

-- | A single-line show instance for functions.
--
-- This is intended to 'Show' functions generated by the 'Listable' instance
-- for functions defined in "Test.LeanCheck.Function.Listable": functions that
-- have finite exceptions to a constant function.  It does work on other types
-- of functions, albeit using @"..."@.
--
-- > > print (&&)
-- > \x y -> case (x,y) of (True,True) -> True; _ -> False
--
-- > > print (==>)
-- > \x y -> case (x,y) of (True,False) -> False; _ -> True
--
-- > > print (==2)
-- > \x -> case x of 2 -> True; _ -> False
--
-- > > print (\x -> abs x < 2)
-- > \x -> case x of 0 -> True; 1 -> True; -1 -> True; _ -> False
--
-- When the function cannot be defined by finite exceptions to a constant
-- function using 8 case-patterns, the rest of the function is represented by
-- @"..."@.
--
-- > > print (+)
-- > \x y -> case (x,y) of (0,0) -> 0; (0,1) -> 1; (1,0) -> 1; (0,-1) -> -1; ...
instance (Show a, Listable a, ShowFunction b) => Show (a->b) where
  showsPrec :: Int -> (a -> b) -> ShowS
showsPrec Int
d  =  Bool -> ShowS -> ShowS
showParen (Int
dInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>Int
0) (ShowS -> ShowS) -> ((a -> b) -> ShowS) -> (a -> b) -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ShowS
forall a. [a] -> [a] -> [a]
(++) (String -> ShowS) -> ((a -> b) -> String) -> (a -> b) -> ShowS
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> (a -> b) -> String
forall a. ShowFunction a => Int -> a -> String
showFunctionLine Int
4