Home > Blockchain >  Avoiding conflicting entries in Haskell associative list
Avoiding conflicting entries in Haskell associative list

Time:04-27

I have the following associative list:

myList :: [(myConcept, String)]
myList = [
  (myInput, "get_input"), 
  (myOutput, "get_output"), 
  (myValues, "get_values")]

-- | Data type
data myConcept = myInput | myOutput | myValues deriving Eq  

I want to ensure that the list does not have any conflicting entries if entries are added. How can this be done? Is it possible have the list Map myConcept String to avoid conflicting entries?

Edit:

I can use the following function to prevent conflicting keys, but I would also like to prevent conflicting values.

addOrReplace :: Eq k => k -> v -> [(k, v)] -> [(k, v)]
addOrReplace key value list = (key,value):(filter ((key /=).fst) list)

I understand recursively checking a list, but how do I check the the value from a pair in an associative list?

checkValue :: Eq v => v -> [(k, v)] -> Bool
checkValue :: value [] = False
checkValue :: value [x] = check value of this entry?
checkValue :: value [x:xs]
    | check value of this entry?
    | otherwise = checkValue value xs 

The other issue with the above is that with an [x:xs] it will return the False and not check the rest of the list. How can I add an if condition where "if false, keep checking the list"?

CodePudding user response:

import qualified Data.Map as MAP
import Data.Maybe
import qualified Data.Bimap as BIMAP

data MyConcept = MyInput | MyOutput | MyValues deriving Eq
myList :: [(MyConcept, String)]
myList = [
  (MyInput, "get_input"),
  (MyOutput, "get_output"),
  (MyValues, "get_values")]

To Start of: your fixed checkValue function:

checkValue :: Eq v => v -> [(k, v)] -> Bool
checkValue str [] = False
checkValue str ((t,v):xs)
    | str == v = True
    | otherwise = checkValue str xs

The generall question you have to ask yourself: should entrys be unique in respective to MyConcept:

(a) schould [(MyInput, "value1"), (MyInput, "value2")] be allowed?

Allso I assume:

(b) MyValues is the only identifier which can hold actual values

-> otherwise it wouldn't make sense to only check on values (= the String part) alone...

Option 1.1: Map assuming (a) isn't allowed:

-- additionally needed:
instance Ord MyConcept where
  compare m1 m2
    | m1 == m2 = EQ
    | otherwise = LT -- not good but practical

type List_Map1 = MAP.Map MyConcept (MyConcept, String)


add1 :: String -> List_Map1 -> List_Map1
add1 str list = if isNothing value
                  then MAP.insert MyValues (MyValues, str) list
                  else error "insert here your prefered runtime error message"
  where
    value = MAP.lookup MyValues list

Option 1.2: Map assuming (a) is allowed:

type List_Map2 = MAP.Map String (MyConcept, String)

add2 :: String -> List_Map2 -> List_Map2
add2 str list = if isNothing value
                  then MAP.insert str (MyValues, str) list
                  else error ""
  where
    value = MAP.lookup str list

Option 2: BiMap

type List_Bimap = BIMAP.Bimap MyConcept (MyConcept, String)

add3 :: String -> List_Bimap -> List_Bimap
add3 str list
  | isNothing value = BIMAP.insert MyValues (MyValues, str) list
  | str == snd (fromJust value) = error "insert here your prefered runtime error message"
  -- Change next line to allow (a)
  | otherwise = error "insert here your prefered runtime error message" 
  where
      value :: Maybe (MyConcept, String)
      value = BIMAP.lookup MyValues list

finally if you prefere simple lists as outputs:

list1 :: String -> List_Map1 -> [(MyConcept, String)]
list1 s l = map snd $ MAP.toList $ add1 s l

list2 :: String -> List_Map2 -> [(MyConcept, String)]
list2 s l = map snd $ MAP.toList $ add2 s l 

list3 :: String -> List_Bimap -> [(MyConcept, String)]
list3 s l = map snd $ BIMAP.toList $ add3 s l

CodePudding user response:

I suspect a Bimap would get you almost everything you want. You might have to write a small wrapper to throw a runtime error (instead of overwriting) on duplicate entries, but it shouldn't be too hard.

  • Related