never executed always true always false
    1 {-# LANGUAGE ConstraintKinds #-}
    2 {-# LANGUAGE FunctionalDependencies #-}
    3 {-# LANGUAGE GADTs #-}
    4 {-# LANGUAGE OverloadedStrings #-}
    5 {-# LANGUAGE TypeFamilies #-}
    6 
    7 {- |
    8 Module      : NITTA.Intermediate.Variable
    9 Description : Types for variable representation
   10 Copyright   : (c) Aleksandr Penskoi, 2021
   11 License     : BSD3
   12 Maintainer  : aleksandr.penskoi@gmail.com
   13 Stability   : experimental
   14 -}
   15 module NITTA.Intermediate.Variable (
   16     Var,
   17     Variables (..),
   18     Suffix (..),
   19 ) where
   20 
   21 import Data.Hashable
   22 import Data.List (stripPrefix)
   23 import Data.Set qualified as S
   24 import Data.String
   25 import Data.String.ToString
   26 import Data.Text qualified as T
   27 import Data.Typeable
   28 
   29 -- | Variable identifier. Used for simplify type description.
   30 type Var v = (Typeable v, Ord v, IsString v, ToString v, Suffix v, Hashable v)
   31 
   32 -- | Type class of something, which is related to variables.
   33 class Variables a v | a -> v where
   34     -- | Get all related variables.
   35     variables :: a -> S.Set v
   36 
   37 -- | The type class for variable identifier modifications.
   38 class Suffix v where
   39     -- | Make a buffered version of the variable. For example: @"v" -> "v@buf"@
   40     bufferSuffix :: v -> v
   41 
   42     -- | Buffer sequence length of a variable (@"v" -> 0; "v@buf" -> 1; "b@buf@buf" -> 2@)
   43     countSuffix :: v -> Int
   44 
   45 -- FIXME: unsafe, because can create duplicate variable. Solution options:
   46 --
   47 -- - unsafeIO and counter;
   48 -- - restriction on user's variable names + checking collision for each variable generation.
   49 instance Suffix String where
   50     bufferSuffix s = s ++ "@buf"
   51     countSuffix [] = 0
   52     countSuffix s
   53         | Just s' <- stripPrefix "@buf" s = 1 + countSuffix s'
   54         | otherwise = countSuffix $ drop 1 s
   55 
   56 instance Suffix T.Text where
   57     bufferSuffix s = s <> "@buf"
   58     countSuffix s | s == T.empty = 0
   59     countSuffix s
   60         | Just s' <- T.stripPrefix "@buf" s = 1 + countSuffix s'
   61         | otherwise = countSuffix $ T.drop 1 s