DEV Community

Pandu Supriyono
Pandu Supriyono

Posted on

Haskell voor beginners: KIX-codes genereren voor postsorteermachines

De KIX-code

Bij het sorteren van post wordt er bij postbedrijven gebruik gemaakt van sorteermachines die streepjescodes scannen om de post beter te verwerken. Op deze codes (de KIX-codes, ofwel klantindexcodes) staan naar welk postcode en huisnummer de post voor bestemd is.

In dit artikel leer je hoe je een adresgegeven transformeert naar een KIX-code. Dit kan handig zijn als je programmatisch je (bedrijfs)post genereert. Denk bijvoorbeeld aan een dashboard voor je bedrijf waarin je automatisch brieven kan maken voor je klanten.

Hoe een KIX-code in elkaar zit

In het algemeen zijn KIX-codes zo geformatteerd:

{POSTCODE}{HUISNUMMER}

Bij een adres met toevoeging zien ze er zo uit:

{POSTCODE}{HUISNUMMER}X{TOEVOEGING}

Dus bij het adres:
Havendijk 156-2, 1231 GF POSTDAM
is de KIX-code als volgt:
1231GF156X2

Op een envelop wordt deze KIX-code weergegeven door een speciaal lettertype die ervoor zorgt dat de code een streepjescode wordt:

Een streepjescode van de KIX-code 1231GF156X2

Patronen vinden in hoe KIX-codes worden gecodeerd

Laten we stilstaan bij hoe je een KIX-code programmatisch kan genereren van een adresgegeven. Dit is goed te doen door het algoritme op te splitsen in kleine stukjes.

Als het goed is kom je uit op:

  • Normaliseer de postcode door spaties te verwijderen en alle letters tot hoofdletters maken
  • Splits de huisnummertoevoeging van het huisnummer middels de 'X'-teken.

Wat handig is om te weten is dat alles na een streepje in het huisnummer wordt geacht als een huisnummertoevoeging.

Functies maken op Haskell

Laten wij beginnen met het definiëren van een adresgegeven op Haskell via een datatype genaamd Adress:

data Address = Address 
  { streetName :: String  
  , houseNumber :: String
  , placeName :: String
  , extension :: Maybe String
  , postcode :: String
  } deriving (Eq, Show)
Enter fullscreen mode Exit fullscreen mode

Een huisnummertoevoeging die expliciet is gegeven (dus die niet achter een streepje zit bij een huisnummer) is optioneel en dus een Maybe String.

Postcode normaliseren

Onze functie normalizePostcode heeft als type signature String -> String. Een String is in feite een lijst van karakters, dus: [Char]. Hierdoor kan je dit invoeren als parameter voor de filter en map functies.

Met filter willen wij een lijst terug van alle letters die niet spaties zijn en met map willen wij alle letters tot hoofdletter maken. Met pipe (.) kan je de output van de filter doorgeven aan de input van de map.

import Data.Char (toUpper)

normalizePostcode :: String -> String
normalizePostcode = filter(/= ' ') . map toUpper
Enter fullscreen mode Exit fullscreen mode

Huisnummertoevoeging pakken van huisnnummer

parseExtensionFromHouseNumber :: String -> String
parseExtensionFromHouseNumber [] = []
parseExtensionFromHouseNumber (x:xs)
  | x == '-' = "X" ++ map toUpper xs
  | otherwise = parseExtensionFromHouseNumber xs
Enter fullscreen mode Exit fullscreen mode

Als je '321-k1' zet op een huisnummer dan krijg je met deze functie XK1 als resultaat, en bij '321' krijg je ''.

Huisnummertoevoeging verwijderen van huisnummer

dropExtensionFromHouseNumber :: String -> String
dropExtensionFromHouseNumber [] = []
dropExtensionFromHouseNumber (x:xs)
  | x == '-' = []
  | otherwise = x:dropExtensionFromHouseNumber xs
Enter fullscreen mode Exit fullscreen mode

Bij '321-k1' krijg je '321' en bij '321 krijg je '321'.

Huisnummertoevoeging pakken van adresgegeven

getExtension :: Address -> String
getExtension a = case extension a of
  Just n -> "X" ++ n
  Nothing -> parseExtensionFromHouseNumber $ houseNumber a
Enter fullscreen mode Exit fullscreen mode

Alles bij elkaar

Nu is het tijd om alle kleine functies in te zetten voor een grotere functie addressToKixCode wat een Address neemt en een String teruggeeft.

addressToKixCode :: Address -> String
addressToKixCode a = normalizedPostcode ++ normalizedHouseNumber ++ extension
  where normalizedPostcode = normalizePostcode $ postcode a
        normalizedHouseNumber = dropExtensionFromHouseNumber $ houseNumber a
        extension = getExtension a
Enter fullscreen mode Exit fullscreen mode

Conclusie en evaluatie

Zoals je hebt gezien is het handig om een grotere vraagstuk op te splitsen in kleine stukjes om deze vervolgens bij elkaar te brengen zodat je veel kleine functies hebt die je individueel kan testen en evalueren. Zo hebben wij een basisfunctie gemaakt om een KIX-code te maken van een adresgegeven. Echter, valt deze functie uit te breiden door ook antwoordnummers en postbussen te integreren in plaats van alleen huisnummers. In een volgende blogbericht zal je zien hoe dat gedaan kan worden.

Bronnen

Zie voor meer informatie over de KIX-code op de website van PostNL.

Discussion (0)