Last active
April 29, 2025 13:13
-
-
Save andrejbauer/5ead3af68457bcfe724cbb7bef19b298 to your computer and use it in GitHub Desktop.
A Haskell implementation of Myhill's isomorphism theorem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Myhill where | |
import Data.List (find) | |
type N = Integer | |
-- given injective maps `f, g : N → N` that witness 1-1 reductions `A ≤₁ B` and `B ≤₁ A`, respectively, | |
-- `myhill f g` computes the graph of a bijection `h : N → N` that witnesses `A ≡ B`, see | |
-- https://en.wikipedia.org/wiki/Myhill_isomorphism_theorem | |
myhill :: (N -> N) -> (N -> N) -> [(N,N)] | |
myhill f g = iterate1 0 [] where | |
iterate1 :: N -> [(N,N)] -> [(N,N)] | |
iterate1 z lst = if any (\(x,y) -> x == z) lst then iterate2 z lst else (z,y) : iterate2 z ((z,y) : lst) | |
where y = search1 z | |
search1 x = let y = f x in maybe y (search1 . fst) . find ((==) y . snd) $ lst | |
iterate2 :: N -> [(N,N)] -> [(N,N)] | |
iterate2 z lst = if any (\(x,y) -> y == z) lst then iterate1 (succ z) lst else (x, z) : iterate1 (succ z) ((x,z) : lst) | |
where x = search2 z | |
search2 y = let x = g y in maybe x (search2 . snd) . find ((==) x . fst) $ lst | |
example1 = take 20 $ myhill (\k -> k) (\k -> k) | |
-- output: [(0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19)] | |
example2 = take 20 $ myhill (\k -> 2 * k + 3) (\k -> k + 1) | |
-- output: [(0,3),(1,0),(2,1),(3,2),(4,11),(5,4),(6,5),(7,6),(8,7),(9,8),(10,9),(11,10),(12,27),(13,12),(14,13),(15,14),(16,15),(17,16),(18,17),(19,18)] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment