Advertisement
multifacs

Haskell Call By Value

Jun 9th, 2024
749
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Haskell 4.80 KB | Source Code | 0 0
  1. {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
  2. {-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
  3.  
  4. module Main where
  5.  
  6. import System.Environment (getArgs)
  7.  
  8. data Term
  9.   = TmVar Int Int
  10.   | TmAbs Term
  11.   | TmApp Term Term
  12.   deriving (Show)
  13.  
  14. termShift :: Int -> Term -> Term
  15. termShift d = walk 0
  16.   where
  17.     walk c t = case t of
  18.       TmAbs t1 -> TmAbs (walk (c + 1) t1)
  19.       TmApp t1 t2 -> TmApp (walk c t1) (walk c t2)
  20.       TmVar x n ->
  21.         if x >= c
  22.           then TmVar (x + d) (n + d)
  23.           else TmVar x (n + d)
  24.  
  25. termSubst :: Int -> Term -> Term -> Term
  26. termSubst j s = walk 0
  27.   where
  28.     walk c t = case t of
  29.       TmAbs t1 -> TmAbs (walk (c + 1) t1)
  30.       TmApp t1 t2 -> TmApp (walk c t1) (walk c t2)
  31.       TmVar x _ ->
  32.         if x == j + c
  33.           then termShift c s
  34.           else t
  35.  
  36. termSubstTop :: Term -> Term -> Term
  37. termSubstTop s t = termShift (-1) (termSubst 0 (termShift 1 s) t)
  38.  
  39. isVal :: Term -> Bool
  40. isVal TmAbs {} = True
  41. isVal _ = False
  42.  
  43. eval1 :: Term -> Maybe Term
  44. eval1 t = case t of
  45.   TmApp (TmAbs t12) v2
  46.     | isVal v2 ->
  47.         return $ termSubstTop v2 t12
  48.   TmApp v1 t2 | isVal v1 -> do
  49.     t2' <- eval1 t2
  50.    return $ TmApp v1 t2'
  51.   TmApp t1 t2 -> do
  52.     t1' <- eval1 t1
  53.    return $ TmApp t1' t2
  54.   _ -> Nothing
  55.  
  56. eval :: Term -> Term
  57. eval t = maybe t eval (eval1 t)
  58.  
  59. -- Wrapper around Term to include a recursion counter
  60. data TrackedTerm = TrackedTerm
  61.   { termVal :: Term,
  62.     counter :: Int
  63.   }
  64.   deriving (Show)
  65.  
  66. -- Increment the counter in the TrackedTerm
  67. increment :: TrackedTerm -> TrackedTerm
  68. increment (TrackedTerm t c) = TrackedTerm t (c + 1)
  69.  
  70. -- A version of eval that tracks the number of recursive calls
  71. -- Modified evalTracked to respect stepsLimit
  72. evalTracked :: Int -> TrackedTerm -> TrackedTerm
  73. evalTracked stepsLimit trackedTerm@(TrackedTerm t c)
  74.   | c >= stepsLimit = trackedTerm  -- Stop if we've reached the step limit
  75.   | otherwise = case eval1 t of
  76.       Nothing -> trackedTerm  -- No more reductions can be done
  77.       Just t' -> evalTracked stepsLimit (increment (TrackedTerm t' c))
  78.  
  79. -- To use evalTracked, you start with a counter of 0
  80. -- Modified evalWithCounter to take stepsLimit and initiate evalTracked with it
  81. evalWithCounter :: Term -> Int -> TrackedTerm
  82. evalWithCounter t stepsLimit = evalTracked stepsLimit (TrackedTerm t 0)
  83.  
  84. -- Process a single term, returning the result as a string
  85. processTerm :: Term -> Int -> IO String
  86. processTerm inputTerm limit = do
  87.       let TrackedTerm resultTerm reductionsCount = evalWithCounter inputTerm limit
  88.       return $
  89.         if (reductionsCount == 0) || (reductionsCount == limit) then "0"
  90.         else show resultTerm
  91.           ++ ","
  92.           ++ show reductionsCount
  93.  
  94. nativeT :: Int -> Int -> Int
  95. nativeT 0 m = m
  96. nativeT n m =
  97.   nativeT (n - 1) (m + 1)
  98.     + sum [nativeT i m * nativeT (n - 1 - i) m | i <- [0 .. n - 1]]
  99.  
  100. appTerm :: Int -> Int -> Int -> Int -> Term
  101. appTerm maxFreeVarCnt termSize j h
  102.   | h <= tjmtnjm =
  103.       let dv = (h - 1) `div` tnjm
  104.           md = (h - 1) `mod` tnjm
  105.           newApp = TmApp (unRankT j maxFreeVarCnt (dv + 1)) (unRankT (termSize - j) maxFreeVarCnt (md + 1))
  106.        in newApp
  107.   | otherwise = appTerm maxFreeVarCnt termSize (j + 1) (h - tjmtnjm)
  108.   where
  109.     tnjm = nativeT (termSize - j) maxFreeVarCnt
  110.     tjmtnjm = nativeT j maxFreeVarCnt * tnjm
  111.  
  112. unRankT :: Int -> Int -> Int -> Term
  113. unRankT termSize maxFreeVarCnt numberOfTerm
  114.   | termSize == 0 = TmVar (numberOfTerm - 1) (numberOfTerm - 1 + 1)
  115.   | numberOfTerm <= nativeT (termSize - 1) (maxFreeVarCnt + 1) = TmAbs (unRankT (termSize - 1) (maxFreeVarCnt + 1) numberOfTerm)
  116.   | otherwise = appTerm maxFreeVarCnt (termSize - 1) 0 (numberOfTerm - nativeT (termSize - 1) (maxFreeVarCnt + 1))
  117.  
  118. generateTerm :: Int -> Int -> Int -> Term
  119. generateTerm = unRankT
  120.  
  121. -- main :: IO ()
  122. -- main = do
  123. --   let term_size = (8 :: Int)
  124. --   let term_num = (443769 :: Int)
  125. --   putStr (show term_size ++ "," ++ show term_num ++ ",")
  126. --   let term = generateTerm 8 0 443769
  127. --   putStr (show term ++ ",")
  128. --   resultString <- processTerm term
  129. --   putStr resultString
  130. --   putStr "\n"
  131.  
  132. main :: IO ()
  133. main = do
  134.   args <- getArgs
  135.   case args of
  136.     [maxSizeStr] -> do
  137.       let maxSize = read maxSizeStr :: Int
  138.       writeFile "data.csv" ""
  139.       mapM_ processSize [1..maxSize]
  140.     _ -> putStr "Wrong argument"
  141.  
  142. -- Process each size
  143. processSize :: Int -> IO ()
  144. processSize size = do
  145.   let maxNum = nativeT size 0
  146.   mapM_ (processTermForSize size) [1..maxNum]
  147.  
  148. -- Process each term for a given size and number
  149. processTermForSize :: Int -> Int -> IO ()
  150. processTermForSize size num = do
  151.   let term = generateTerm size 0 num
  152.   resultString <- processTerm term (size * 15)
  153.   appendFile "data.csv" (if resultString == "0" then "" else show size ++ "," ++ show num ++ "," ++ resultString ++ "\n")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement