I’m new to Haskell (as you can probably see in my code) and I wanted to make a simple Brainf### interpreter:
import Text.Read (readMaybe)
import Data.Maybe (fromJust)
import Data.List (findIndex)
import Data.Char (chr, ord)
import System.IO
findPairs :: [Int] -> [Char] -> [(Int, Int)] -> Int -> [(Int, Int)]
findPairs stack [] pairs _ = if stack == [] then pairs else error "Mismatched parentheses"
findPairs stack (x:xs) pairs index = findPairs (if x == '[' then index : stack else (if x == ']' then tail stack else stack)) xs (if x == ']' then (head stack, index) : pairs else pairs) (current + 1)
BrainfuckRec :: [Int] -> Int -> [Char] -> [(Int, Int)] -> Int -> IO ( )
BrainfuckRec arr ptr code pairs current =
if current == length code then "nn<Program terminated>"
else case code !! current of
'+' -> BrainfuckRec ((take ptr arr) ++ [((arr !! ptr) + 1) `mod` 128] ++ drop (ptr + 1) arr) ptr code pairs (current + 1)
'-' -> BrainfuckRec ((take ptr arr) ++ [if arr !! ptr == 0 then 127 else arr((arr !! ptr) - 1) `mod` 128] ++ (drop (ptr + 1) arr)) ptr code pairs (current + 1)
'<' -> BrainfuckRec (if ptr > 0 then arr else 0 : arr) (if ptr > 0 then ptr - 1 else 0) code pairs (current + 1)
'>' -> BrainfuckRec (if ptr == (length arr) - 1 then arr ++ [0] else arr) (ptr + 1) code pairs (current + 1)
'[' -> BrainfuckRec arr ptr code pairs (fst (pairs !! (findIndex ((== current) . snd) pairs)))
']' -> BrainfuckRec arr ptr code pairs (snd (pairs !! (findIndex ((== current) . fst) pairs)))
'.' -> do
putChar(chr (arr !! ptr))
return BrainfuckRec arr ptr code pairs (index + 1)
',' -> do
input <- getLine
let temp = case parseInt input of Just x -> x
Nothing -> ord (head input)
return BrainfuckRec ((take ptr arr) ++ [temp] ++ drop (ptr + 1) arr) arr ptr code pairs (current + 1)
Brainfuck :: [Char] -> IO ( )
Brainfuck inputFile = Brainfuck [0] 0 (readFile inputFile ReadMode) (findPairs [] code [] 0) 0
parseInt :: [Char] -> Maybe Int
parseInt = readMaybe
but, at BrainfuckRec :: [Int] -> Int -> [Char] -> [(Int, Int)] -> Int -> IO ( )
, I got this error:
• Invalid type signature: BrainfuckRec :: …
• A type signature should be of form ::
(It won’t show the text for some reason)
I tried asking ChatGPT to fix it, but it failed over and over. When I decided to ask this question, the code looked like this:
import Text.Read (readMaybe)
import Data.List (findIndex)
import Data.Char (chr, ord)
-- Match brackets for loops
findPairs :: [Int] -> [Char] -> [(Int, Int)] -> Int -> [(Int, Int)]
findPairs [] [] pairs _ = pairs
findPairs [] (']':_) _ idx = error ("Unmatched ']' at " ++ show idx)
findPairs stack [] pairs idx = error ("Unmatched '[' at " ++ show idx)
findPairs stack (x:xs) pairs idx
| x == '[' = findPairs (idx : stack) xs pairs (idx + 1)
| x == ']' = case stack of
[] -> error ("Unmatched ']' at " ++ show idx)
(s:st) -> findPairs st xs ((s, idx) : pairs) (idx + 1)
| otherwise = findPairs stack xs pairs (idx + 1)
-- Recursive Brainfuck interpreter
BrainfuckRec :: [Int] -> Int -> [Char] -> [(Int, Int)] -> Int -> IO ()
BrainfuckRec arr ptr code pairs current =
if current == length code then putStrLn "nn<Program terminated>"
else case code !! current of
'+' -> BrainfuckRec ((take ptr arr) ++ [((arr !! ptr) + 1) `mod` 128] ++ drop (ptr + 1) arr) ptr code pairs (current + 1)
'-' -> BrainfuckRec ((take ptr arr) ++ [if arr !! ptr == 0 then 127 else ((arr !! ptr) - 1) `mod` 128] ++ drop (ptr + 1) arr) ptr code pairs (current + 1)
'<' -> BrainfuckRec arr (if ptr > 0 then ptr - 1 else 0) code pairs (current + 1)
'>' -> BrainfuckRec (if ptr == length arr - 1 then arr ++ [0] else arr) (ptr + 1) code pairs (current + 1)
'[' -> case findIndex ((== current) . snd) pairs of
Just idx -> BrainfuckRec arr ptr code pairs (if arr !! ptr == 0 then fst (pairs !! idx) else current + 1)
Nothing -> error $ "Unmatched '[' at position " ++ show current
']' -> case findIndex ((== current) . fst) pairs of
Just idx -> BrainfuckRec arr ptr code pairs (if arr !! ptr /= 0 then snd (pairs !! idx) else current + 1)
Nothing -> error $ "Unmatched ']' at position " ++ show current
'.' -> do
putChar (chr (arr !! ptr))
BrainfuckRec arr ptr code pairs (current + 1)
',' -> getLine >>= input ->
let temp = case parseInt input of
Just x -> if x >= 0 && x < 128 then x else error "Invalid ASCII value!"
Nothing -> ord (head input)
in BrainfuckRec ((take ptr arr) ++ [temp] ++ drop (ptr + 1) arr) ptr code pairs (current + 1)
-- Main Brainfuck interpreter
Brainfuck :: String -> IO ()
Brainfuck inputFile = do
code <- readFile inputFile
let pairs = findPairs [] code [] 0
BrainfuckRec [0] 0 code pairs 0
-- Parse integer input
parseInt :: [Char] -> Maybe Int
parseInt = readMaybe
But the error is still there. What’s causing it? How do I fix it?
Victor PISLARU is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
1