From e4d64b2cf663d2f4a564a57444285a5a390968d8 Mon Sep 17 00:00:00 2001 From: karim <kwsa1g20@soton.ac.uk> Date: Thu, 26 Oct 2023 09:54:47 +0100 Subject: [PATCH] rest --- Parsing.hs | 122 +++++++++++++++++++++++++++++++++++ Testing.hs | 18 ++++++ Trial.hs | 1 + dist-newstyle/.DS_Store | Bin 0 -> 6148 bytes dist-newstyle/cache/compiler | Bin 0 -> 13015 bytes 5 files changed, 141 insertions(+) create mode 100644 Parsing.hs create mode 100644 Testing.hs create mode 100644 Trial.hs create mode 100644 dist-newstyle/.DS_Store create mode 100644 dist-newstyle/cache/compiler diff --git a/Parsing.hs b/Parsing.hs new file mode 100644 index 0000000..1974be1 --- /dev/null +++ b/Parsing.hs @@ -0,0 +1,122 @@ +-- Functional parsing library from chapter 13 of Programming in Haskell, +-- Graham Hutton, Cambridge University Press, 2016. + +module Parsing (module Parsing, module Control.Applicative) where + +import Control.Applicative +import Data.Char + +-- Basic definitions + +newtype Parser a = P (String -> [(a,String)]) + +parse :: Parser a -> String -> [(a,String)] +parse (P p) inp = p inp + +item :: Parser Char +item = P (\inp -> case inp of + [] -> [] + (x:xs) -> [(x,xs)]) + +-- Sequencing parsers + +instance Functor Parser where + -- fmap :: (a -> b) -> Parser a -> Parser b + fmap g p = P (\inp -> case parse p inp of + [] -> [] + [(v,out)] -> [(g v, out)]) + +instance Applicative Parser where + -- pure :: a -> Parser a + pure v = P (\inp -> [(v,inp)]) + + -- <*> :: Parser (a -> b) -> Parser a -> Parser b + pg <*> px = P (\inp -> case parse pg inp of + [] -> [] + [(g,out)] -> parse (fmap g px) out) + +instance Monad Parser where + -- (>>=) :: Parser a -> (a -> Parser b) -> Parser b + p >>= f = P (\inp -> case parse p inp of + [] -> [] + [(v,out)] -> parse (f v) out) + +-- Making choices + +instance Alternative Parser where + -- empty :: Parser a + empty = P (\inp -> []) + + -- (<|>) :: Parser a -> Parser a -> Parser a + p <|> q = P (\inp -> case parse p inp of + [] -> parse q inp + [(v,out)] -> [(v,out)]) + +-- Derived primitives + +sat :: (Char -> Bool) -> Parser Char +sat p = do x <- item + if p x then return x else empty + +digit :: Parser Char +digit = sat isDigit + +lower :: Parser Char +lower = sat isLower + +upper :: Parser Char +upper = sat isUpper + +letter :: Parser Char +letter = sat isAlpha + +alphanum :: Parser Char +alphanum = sat isAlphaNum + +char :: Char -> Parser Char +char x = sat (== x) + +string :: String -> Parser String +string [] = return [] +string (x:xs) = do char x + string xs + return (x:xs) + +ident :: Parser String +ident = do x <- lower + xs <- many alphanum + return (x:xs) + +nat :: Parser Int +nat = do xs <- some digit + return (read xs) + +int :: Parser Int +int = do char '-' + n <- nat + return (-n) + <|> nat + +-- Handling spacing + +space :: Parser () +space = do many (sat isSpace) + return () + +token :: Parser a -> Parser a +token p = do space + v <- p + space + return v + +identifier :: Parser String +identifier = token ident + +natural :: Parser Int +natural = token nat + +integer :: Parser Int +integer = token int + +symbol :: String -> Parser String +symbol xs = token (string xs) diff --git a/Testing.hs b/Testing.hs new file mode 100644 index 0000000..312a5fd --- /dev/null +++ b/Testing.hs @@ -0,0 +1,18 @@ +import Challenges +challenge1Test1 = (calcBBInteractions (-8) [] [(North,1)]) == error "grid must be larger 0*0" +challenge1Test2 = (calcBBInteractions (8) [] [(North,1)]) == [((North,1),Path (South,1))] && (calcBBInteractions (8) [(2,3),(1,8)] []) == [] && calcBBInteractions 4 [(3,4)] [(North,2)] == [((North,2), Path (West,3))] && calcBBInteractions 4 [(1,1)] [(North,2)] == [((North,2),Reflect)] && calcBBInteractions 4 [(2,3)] [(North,2)] == [((North,2),Absorb)] + + +challenge3Tests = prettyPrint (LamVar 1) == "x1" && prettyPrint (LamAbs 1 (LamVar 1)) == "\\x0->x0" && prettyPrint (LamApp (LamAbs 2 (LamVar 5)) (LamVar 3)) == "(\\x0->x5)x3" && prettyPrint (LamAbs 1 ( LamAbs 2 (LamApp (LamAbs 1 (LamAbs 4 (LamVar 3))) (LamVar 3)))) == "\\x0->\\x0->(\\x0->\\x0->x3)x3" +challenge3Testserror = prettyPrint (LamAbs 2 (LamVar (-2))) == error " no negative variables" + +challenge4Tests = parseArith "-2" == Nothing && parseArith "2+2" == Just (Add (ArithNum 2) (ArithNum 2)) && parseArith "2+2*3" == Just (Mul (Add (ArithNum 2) (ArithNum 2)) (ArithNum 3)) && parseArith "(+1)*2" == Nothing && parseArith "(+1)2*3" == Just (Mul(SecApp (Section (ArithNum 1)) (ArithNum 2)) (ArithNum 3)) + + + +challenge5Testerror = churchEnc (Add (ArithNum (-2)) (ArithNum 3)) == error " no negative numbers " +challenge5Test = churchEnc (ArithNum 4) == LamAbs 0 (LamAbs 1 (LamApp (LamVar 0) (LamApp (LamVar 0) (LamApp (LamVar 0) (LamApp (LamVar 0) (LamVar 1)))))) && churchEnc (Mul (ArithNum 3) (ArithNum 4)) == LamApp (LamApp (LamAbs 0 (LamAbs 1 (LamAbs 2 (LamAbs 3 (LamApp (LamApp (LamVar 0) (LamApp (LamVar 1) (LamVar 2))) (LamVar 3)))))) (LamAbs 0 (LamAbs 1 (LamApp (LamVar 0) (LamApp (LamVar 0) (LamApp (LamVar 0) (LamVar 1))))))) (LamAbs 0 (LamAbs 1 (LamApp (LamVar 0) (LamApp (LamVar 0) (LamApp (LamVar 0) (LamApp (LamVar 0) (LamVar 1))))))) + && churchEnc (Add (ArithNum 2) (ArithNum 2)) == LamApp (LamApp (LamAbs 0 (LamAbs 1 (LamAbs 2 (LamAbs 3 (LamApp (LamApp (LamVar 0) (LamVar 2)) (LamApp (LamApp (LamVar 1) (LamVar 2)) (LamVar 3))))))) (LamAbs 0 (LamAbs 1 (LamApp (LamVar 0) (LamApp (LamVar 0) (LamVar 1)))))) (LamAbs 0 (LamAbs 1 (LamApp (LamVar 0) (LamApp (LamVar 0) (LamVar 1))))) + + + diff --git a/Trial.hs b/Trial.hs new file mode 100644 index 0000000..f68c78e --- /dev/null +++ b/Trial.hs @@ -0,0 +1 @@ +foo (3) = (1,3) diff --git a/dist-newstyle/.DS_Store b/dist-newstyle/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d1ecf9a0221b8247c834ff742d1b05423e5fd3e2 GIT binary patch literal 6148 zcmZQzU|@7AO)+F(5MW?n;9!8z45|#6fRTZLft4YdA(0`OA%h_`r8qe!DL+34tdI#z zGBAMDFoMlMm4`}?QllX-8UmvsFd71*Aut*OgD3<*^){&f=N?3E8g<HO2#kin;0OUw z`Je#mD=;uHI6&zJ2n~_~wfn(c07eD|7MP16{Qz*E0HhV92BZ~4gS0X*f>>ZPz*-p? zp;{Ti-4KvIP?rQmgS9g-f^7!z!P*%Z!8S86FhaC5FhXr+1odJ-=0dbHFhaC5FoJD| zxo(sm4S~@RfQ0}vgdqT`|6Lgvu=f8UN=C`i5Eu=C;Ti&rEH1$=PN2#YhYvw@ZUR&e z#0FKxjG#Ihq6b_R!x{lhkO4&rsB%zs53Y(CA#Df{AEbS>Api@YQF=541|S3g%;ytb literal 0 HcmV?d00001 diff --git a/dist-newstyle/cache/compiler b/dist-newstyle/cache/compiler new file mode 100644 index 0000000000000000000000000000000000000000..a7d2d8ca349bdbf0f66281c17b74ba99a23b9d56 GIT binary patch literal 13015 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 Wh|oZX<q{kl4DfEM0GS7F3IhO%6_-%} literal 0 HcmV?d00001 -- GitLab