Peel the potatoes and cut them into even ½-inch (1.25 cm) cubes. Dice the onion, carrots, and celery into small uniform pieces, mince the garlic, dice the ham into bite-sized cubes, and shred the cheddar on a box grater.
Melt the butter in a Dutch oven over medium heat until it foams. Add the onion, carrots, and celery and cook for 5 to 6 minutes until the onion turns translucent and the vegetables soften. Stir in the minced garlic and cook for 1 more minute, just until fragrant.
Sprinkle the flour evenly over the vegetables and stir constantly for 1 to 2 minutes, coating everything, until the raw flour smell cooks off and the mixture looks like wet sand. Keep the heat at medium so the flour toasts without scorching.
Pour in the chicken broth slowly, whisking as you go to break up any lumps. Add the diced potatoes, thyme, smoked paprika, bay leaves, and black pepper. Bring to a gentle boil, then reduce to a simmer and cook uncovered for 15 to 18 minutes, until a fork slides easily into the potato cubes.
For a thicker, creamier base, mash some of the cooked potatoes against the side of the pot with a potato masher, or pulse briefly with an immersion blender. Leave plenty of whole potato pieces for texture; blending about a third of the pot gives the best balance.
Lower the heat so the soup is no longer boiling. Stir in the whole milk and heavy cream, then add the diced ham. Warm everything through for 4 to 5 minutes, stirring often, without letting it reach a boil.
Remove the pot from the heat and discard the bay leaves. Add the shredded cheddar a handful at a time, stirring until each addition melts into the broth. Taste, then add salt and extra pepper as needed.
Ladle the soup into bowls while hot. Top with chopped chives or green onion, a little extra cheddar, and crumbled bacon if you like.