以下是本书{" Haskell School of Expression"的source code示例。
我没有看到书中解释的这种源代码格式,对我来说没有意义。
为什么标有<
的行不一定是可执行的?
此代码中的所有内容对我来说都是可执行的。
我应该如何解释<
,>
符号?
为什么不简单地使用简单的Haskell代码?什么是这些额外的符号?
如何将此代码转换为简单的Haskell?
我在询问之前搜索过网,但对这个话题并没有太多了解。
This code was automatically extracted from a .lhs file that
uses the following convention:
-- lines beginning with ">" are executable
-- lines beginning with "<" are in the text,
but not necessarily executable
-- lines beginning with "|" are also in the text,
but are often just expressions or code fragments.
< reactimate :: String -> Behavior Graphic -> IO ()
< color1 :: Behavior Color
< color1 = red `untilB` (lbp ->> blue)
< ball1 :: Behavior Picture
< ball1 = paint color1 circ
< circ :: Behavior Region
< circ = translate (cos time, sin time) (ell 0.2 0.2)
< test beh = reactimate "FAL Test" (lift1 picToGraphic beh)
< color1r = red `untilB` lbp ->>
< blue `untilB` lbp ->>
< color1r
< color2 = red `untilB` ((lbp ->> blue) .|. (key ->> yellow))
< color2r = red `untilB` colorEvent where
< colorEvent = (lbp ->> blue `untilB` colorEvent) .|.
< (key ->> yellow `untilB` colorEvent)
< color2h = red `switch` ((lbp ->> blue) .|. (key ->> yellow))
< color1h = red `switch` (lbp `withElem_` cycle [blue,red])
< color3 = white `switch` (key =>> \c ->
< case c of 'R' -> red
< 'B' -> blue
< 'Y' -> yellow
< _ -> white )
< color4 = white `switch` ((key `snapshot` color4) =>> \(c,old) ->
< case c of 'R' -> red
< 'B' -> blue
< 'Y' -> yellow
< _ -> lift0 old)
< color5 = red `untilB` (when (time >* 5) ->> blue)
< s,v :: Behavior Float
< s = s0 + integral v
< v = v0 + integral f
< ball2 = paint red (translate (x,y) (ell 0.2 0.2))
< where g = -4
< x = -3 + integral 0.5
< y = 1.5 + integral v
< v = integral g `switch` (hit `snapshot_` v =>> \v'->
< lift0 (-v') + integral g)
< hit = when (y <* -1.5)
> module Fal where
>
> import SOE hiding (Region, Event)
> import qualified SOE as G (Region, Event)
> import Animation (picToGraphic)
> import Shape
> import Picture
> import Memo1
> import Draw (xWin,yWin,intToFloat)
> -- import Word (word32ToInt)
> import Control.Concurrent.Chan
> infixr 1 =>>, ->>
> infixr 1 `untilB`, `switch`, `stepAccum`, `step`
> infixl 0 .|.
> infixr 4 <*, >*
> infixr 3 &&*
> infixr 2 ||*
> type Time = Float
< data G.Event
< = Key { char :: Char, isDown :: Bool }
< | Button { pt :: Point, isLeft, isDown :: Bool }
< | MouseMove { pt :: Point }
< | Resize
< | Closed
< deriving Show
> type UserAction = G.Event
< data G.Event
< = Key Char Bool
< | Button Point Bool Bool
< | MouseMove Point
< | Resize
< | Closed
< deriving Show
< k = Key 'a' True
< b = Button (0,0) True False
< k = Key { char = 'a', isDown = True }
< b = Button { pt = (0,0), isLeft = True, isDown = False }
< k = Key { isDown = True, char = 'a' }
< b = Button { isLeft = True, isDown = False, pt = (0,0) }
| char k ==> 'a'
| char b ==> error ...
| isDown k ==> True
| isDown b ==> False
| k { char = 'b' } ==> Key 'b' True
< incr (Button { pt = (x,y) }) = (x+1,y+1)
> newtype Behavior1 a
> = Behavior1 ([(UserAction,Time)] -> Time -> a)
> inList :: [Int] -> Int -> Bool
> inList xs y = elem y xs
> result1 :: [Bool]
> result1 = map (inList xs) ys
> xs = [2,4,6,8,10] :: [Int]
> ys = [3,6,9] :: [Int]
> result2 :: [Bool]
> result2 = manyInList xs ys
>
> manyInList :: [Int] -> [Int] -> [Bool]
> manyInList [] _ = []
> manyInList _ [] = []
> manyInList (x:xs) (y:ys) =
> if x<y then manyInList xs (y:ys)
> else (x==y) : manyInList (x:xs) ys
< bf :: [(UserAction,Time)] -> Time -> a
< inList :: [Int] -> Int -> Bool
> newtype Behavior2 a
> = Behavior2 ([(UserAction,Time)] -> [Time] -> [a])
< manyInList :: [Int] -> [Int] -> [Bool]
> newtype Behavior3 a
> = Behavior3 ([UserAction] -> [Time] -> [a])
> newtype Behavior4 a
> = Behavior4 ([Maybe UserAction] -> [Time] -> [a])
> newtype Behavior a
> = Behavior (([Maybe UserAction],[Time]) -> [a])
< type Event a = Behavior (Maybe a)
> newtype Event a
> = Event (([Maybe UserAction],[Time]) -> [Maybe a])
> time :: Behavior Time
> time = Behavior (\(_,ts) -> ts)
> constB :: a -> Behavior a
> constB x = Behavior (\_ -> repeat x)
< red, blue :: Behavior Color
< red = constB Red
< blue = constB Blue
> ($*) :: Behavior (a->b) -> Behavior a -> Behavior b
> Behavior ff $* Behavior fb
> = Behavior (\uts -> zipWith ($) (ff uts) (fb uts))
> lift0 :: a -> Behavior a
> lift0 = constB
> lift1 :: (a -> b) -> (Behavior a -> Behavior b)
> lift1 f b1
> = lift0 f $* b1
> lift2 :: (a -> b -> c) -> (Behavior a -> Behavior b -> Behavior c)
> lift2 f b1 b2
> = lift1 f b1 $* b2
> lift3 :: (a -> b -> c -> d) ->
> (Behavior a -> Behavior b -> Behavior c -> Behavior d)
> lift3 f b1 b2 b3
> = lift2 f b1 b2 $* b3
> pairB :: Behavior a -> Behavior b -> Behavior (a,b)
> pairB = lift2 (,)
> fstB :: Behavior (a,b) -> Behavior a
> fstB = lift1 fst
> sndB :: Behavior (a,b) -> Behavior b
> sndB = lift1 snd
> paint :: Behavior Color -> Behavior Region -> Behavior Picture
> paint = lift2 Region
> red, blue, yellow, green, white, black :: Behavior Color
> red = lift0 Red
> blue = lift0 Blue
> yellow = lift0 Yellow
> green = lift0 Green
> white = lift0 White
> black = lift0 Black
> shape :: Behavior Shape -> Behavior Region
> shape = lift1 Shape
> ell, rec :: Behavior Float -> Behavior Float -> Behavior Region
> ell x y = shape (lift2 Ellipse x y)
> rec x y = shape (lift2 Rectangle x y)
> translate :: (Behavior Float, Behavior Float)
> -> Behavior Region -> Behavior Region
> translate (Behavior fx, Behavior fy) (Behavior fp)
> = Behavior (\uts -> zipWith3 aux (fx uts) (fy uts) (fp uts))
> where aux x y p = Translate (x,y) p
> (>*),(<*) :: Ord a => Behavior a -> Behavior a -> Behavior Bool
> (>*) = lift2 (>)
> (<*) = lift2 (<)
> (&&*),(||*) :: Behavior Bool -> Behavior Bool -> Behavior Bool
> (&&*) = lift2 (&&)
> (||*) = lift2 (||)
> over :: Behavior Picture -> Behavior Picture -> Behavior Picture
> over = lift2 Over
> instance Fractional a => Fractional (Behavior a) where
> (/) = lift2 (/)
> fromRational = lift0 . fromRational
> instance Num a => Num (Behavior a) where
> (+) = lift2 (+)
> (*) = lift2 (*)
> negate = lift1 negate
> abs = lift1 abs
> signum = lift1 signum
> fromInteger = lift0 . fromInteger
> instance Show (Behavior a) where
> showsPrec n a s = "<< Behavior >>"
> instance Eq (Behavior a) where
> a1 == a2 = error "Can't compare behaviors."
> instance Floating a => Floating (Behavior a) where
> pi = lift0 pi
> sqrt = lift1 sqrt
> exp = lift1 exp
> log = lift1 log
> sin = lift1 sin
> cos = lift1 cos
> tan = lift1 tan
> asin = lift1 asin
> acos = lift1 acos
> atan = lift1 atan
> sinh = lift1 sinh
> cosh = lift1 cosh
> tanh = lift1 tanh
> asinh = lift1 asinh
> acosh = lift1 acosh
> atanh = lift1 atanh
>-- untilB, switch :: Behavior a -> Event (Behavior a) -> Behavior a
> Behavior fb `untilB` Event fe =
> memoB $ Behavior (\uts@(us,ts) -> loop us ts (fe uts) (fb uts))
> where loop (_:us) (_:ts) ~(e:es) (b:bs) =
> b : case e of
> Nothing -> loop us ts es bs
> Just (Behavior fb') -> fb' (us,ts)
> memoB :: Behavior a -> Behavior a
memoB = id
> memoB (Behavior fb) = Behavior (memo1 fb)
> Behavior fb `switch` Event fe =
> memoB $ Behavior (\uts@(us,ts) -> loop us ts (fe uts) (fb uts))
> where loop (_:us) (_:ts) ~(e:es) ~(b:bs) =
> b : case e of
> Nothing -> loop us ts es bs
> Just (Behavior fb') -> loop us ts es (fb' (us,ts))
> lbp :: Event ()
> lbp = Event (\(uas,_) -> map getlbp uas)
> where getlbp (Just (Button _ True True)) = Just ()
> getlbp _ = Nothing
< color1 :: Behavior Color
< color1 = red `untilB` lbp ->> blue
< (->>) :: Event () -> Behavior Color -> Event (Behavior Color)
< (->>) :: Event a -> b -> Event b
> (=>>) :: Event a -> (a->b) -> Event b
< Event fe =>> f = Event (\uts -> map aux (fe uts))
< where aux (Just a) = Just (f a)
< aux Nothing = Nothing
> Event fe =>> f = Event (map (fmap f) . fe)
> e ->> v = e =>> \_ -> v
> while :: Behavior Bool -> Event ()
> while (Behavior fb)
> = Event (\uts -> map aux (fb uts))
> where aux True = Just ()
> aux False = Nothing
> unique :: (Show a, Eq a) => Event a -> Event a
> unique (Event fe) =
> Event (\uts -> aux (fe uts))
> where aux xs = zipWith remdup (Nothing:xs) xs
> remdup x y | x==y = Nothing
> | otherwise = y
> when :: Behavior Bool -> Event ()
> when = unique . while
> integral :: Behavior Float -> Behavior Float
> integral (Behavior fb)
> = Behavior (\uts@(us,t:ts) -> 0 : loop t 0 ts (fb uts))
> where loop t0 acc (t1:ts) (a:as)
> = let acc' = acc + (t1-t0)*a
> in acc' : loop t1 acc' ts as
> color1 :: Behavior Color
> color1 = red `untilB` lbp ->> blue
> uas = cycle [Nothing, Just (Button (0,0) True True), Nothing]
> ts = [1,2 ..] :: [Time]
> stream1 = let Behavior fb = color1
> in take 3 (fb (uas,ts))
| lbp (uas,ts)
| let Event fe = lbp
| in fe (uas,ts)
| (lbp ->> blue) (uas,ts)
| ===> (lbp =>> \_-> blue) (uas,ts)
| ===> (map (fmap (\_-> blue)) . fe) (uas,ts)
| !!! where fe (uas,_) = map getlbp uas
| ===> map (fmap (\_-> blue)) (fe (uas,ts))
| !!! where fe (uas,_) = map getlbp uas
| ===> map (fmap (\_-> blue)) (Nothing : Just() : Nothing : ...)
| ===> Nothing : Just blue : Nothing : ...
< tuas = tail uas
< ttuas = tail (tail uas)
< tts = tail ts
< ttts = tail (tail ts)
| (red `switch` (lbp ->> blue)) (uas,ts)
| ===> loop uas ts ((lbp ->> blue) (uas,ts)) (red (uas,ts))
| ===> loop uas ts (Nothing : Just blue : Nothing : ...) (red (uas,ts))
| ===> loop uas ts (Nothing : Just blue : Nothing : ...) (repeat Red)
| ===> loop uas ts (Nothing : Just blue : Nothing : ...) [Red ..]
| ===> Red : loop tuas tts (Just blue : Nothing : ...) [Red ..]
| ===> Red : Red : loop ttuas ttts (Nothing : ...) (blue (ttuas,ttts))
| ===> Red : Red : loop ttuas ttts (Nothing : ...) [Blue..]
| ===> Red : Red : Blue : ...
> test beh = reactimate "FAL Test" (lift1 picToGraphic beh)
> cball1 = paint color1 circ
> cball1r = paint color1r circ
> cball1h = paint color1h circ
> cball2 = paint color2 circ
> cball2r = paint color2r circ
> cball2h = paint color2h circ
> cball3 = paint color3 circ
> cball4 = paint color4 circ
> cball5 = paint color5 circ
> circ = translate (cos time, sin time) (ell 0.2 0.2)
> ball1 :: Behavior Picture
> ball1 = paint color1 circ
> color1r = red `untilB` lbp ->>
> blue `untilB` lbp ->>
> color1r
> color2r = red `untilB` colorEvent where
> colorEvent = (lbp ->> blue `untilB` colorEvent) .|.
> (key ->> yellow `untilB` colorEvent)
> color2h = red `switch` ((lbp ->> blue) .|. (key ->> yellow))
> color5 = red `untilB` when (time >* 5) ->> blue
> sim1 = drawIt "Bouncing Ball"
> (b `Over` Region White (Shape (Rectangle 6 5)))
> drawIt :: String -> Picture -> IO ()
> drawIt s p
> = runGraphics (
> do w <- openWindow s (xWin,yWin)
> drawPic w p
> spaceClose w
> )
> b :: Picture
> b = let Behavior f = ball2Sim
> in foldr Over EmptyPic
> (take 100 (f (repeat Nothing, [0.0, 0.1 ..])))
> ball2Sim = paint red (translate (x,y) (ell 0.08 0.08))
> where g = -4
> x = -3 + integral 0.7
> y = 1.5 + integral v
> v = integral g `switch` (hit `snapshot_` v =>> \v'->
> lift0 (-v') + integral g)
> hit = when (y <* -1.5)
> ball2 = paint red (translate (x,y) (ell 0.2 0.2))
> where g = -4
> x = -3 + integral 0.5
> y = 1.5 + integral v
> v = integral g `switch` (hit `snapshot_` v =>> \v'->
> lift0 (-v') + integral g)
> hit = when (y <* -1.5)
> sim2 = drawIt "Paddleball!!"
> (pb `Over` Region White (Shape (Rectangle 6 5)))
> pb :: Picture
> pb = let Behavior f = paddleball 2
> in f (repeat Nothing, cycle [0.1, 0.2 ..]) !! 3
> color1h = red `switch` (lbp `withElem_` cycle [blue,red])
> withElem :: Event a -> [b] -> Event (a,b)
> withElem (Event fe) bs = Event (\uts -> loop (fe uts) bs)
> where loop (Just a : evs) (b:bs) = Just (a,b) : loop evs bs
> loop (Nothing : evs) bs = Nothing : loop evs bs
> withElem_ :: Event a -> [b] -> Event b
> withElem_ e bs = e `withElem` bs =>> snd
> color2 = red `untilB` (lbp ->> blue .|. key ->> yellow)
> (.|.) :: Event a -> Event a -> Event a
> Event fe1 .|. Event fe2
> = Event (\uts -> zipWith aux (fe1 uts) (fe2 uts))
> where aux Nothing Nothing = Nothing
> aux (Just x) _ = Just x
> aux _ (Just y) = Just y
> key :: Event Char
> key = Event (\(uas,_) -> map getkey uas)
> where getkey (Just (Key ch True)) = Just ch
> getkey _ = Nothing
> color3 = white `switch` (key =>> \c ->
> case c of 'R' -> red
> 'B' -> blue
> 'Y' -> yellow
> _ -> white )
> color4 = white `switch` (key `snapshot` color4 =>> \(c,old) ->
> case c of 'R' -> red
> 'B' -> blue
> 'Y' -> yellow
> _ -> lift0 old)
> snapshot :: Event a -> Behavior b -> Event (a,b)
> Event fe `snapshot` Behavior fb
> = Event (\uts -> zipWith' aux (fe uts) (fb uts))
> where aux (Just x) y = Just (x, y)
> aux Nothing _ = Nothing
> zipWith' f ~(x:xs) ~(y:ys) = f x y : zipWith' f xs ys
> snapshot_ :: Event a -> Behavior b -> Event b
> snapshot_ e b = e `snapshot` b =>> snd
< b1 = b0 `switch` (e `snapshot` b1 =>> b2)
> step :: a -> Event a -> Behavior a
> a `step` e = constB a `switch` e =>> constB
> stepAccum :: a -> Event (a->a) -> Behavior a
> a `stepAccum` e = b
> where b = a `step` (e `snapshot` b =>> uncurry ($))
> counter = 0 `stepAccum` lbp ->> (+1)
> stream2 = let Behavior fb = counter
> in take 20 (fb (uas,ts))
> mm :: Event Coordinate
> mm = Event (\(uas,_) -> map getmm uas)
> where getmm (Just (MouseMove pt)) = Just (gPtToPt pt)
> getmm _ = Nothing
>
> gPtToPt :: (Int, Int) -> Coordinate
> gPtToPt (x,y) = ( pixelToInch (x - 300)
> , pixelToInch (250 - y) )
>
> pixelToInch :: Int -> Float
> pixelToInch n = intToFloat n / 100
> mouse :: (Behavior Float, Behavior Float)
> mouse = (fstB m, sndB m)
> where m = (0,0) `step` mm
< translate :: (Behavior Float, Behavior Float)
< -> Behavior Region -> Behavior Region
> ball3 = paint color4 circ3
> circ3 = translate mouse (ell 0.2 0.2)
> paddleball vel = walls `over` paddle `over` pball vel
> walls = let upper = paint blue (translate ( 0,1.7) (rec 4.4 0.05))
> left = paint blue (translate (-2.2,0) (rec 0.05 3.4))
> right = paint blue (translate ( 2.2,0) (rec 0.05 3.4))
> in upper `over` left `over` right
> paddle = paint red (translate (fst mouse, -1.7) (rec 0.5 0.05))
> pball vel =
> let xvel = vel `stepAccum` xbounce ->> negate
> xpos = integral xvel
> xbounce = when (xpos >* 2 ||* xpos <* -2)
> yvel = vel `stepAccum` ybounce ->> negate
> ypos = integral yvel
> ybounce = when (ypos >* 1.5
> ||* ypos `between` (-2.0,-1.5) &&*
> fst mouse `between` (xpos-0.25,xpos+0.25))
> in paint yellow (translate (xpos, ypos) (ell 0.2 0.2))
> x `between` (a,b) = x >* a &&* x <* b
< timeTrans :: Behavior Time -> Behavior a -> Behavior a
> reactimate :: String -> Behavior Graphic -> IO ()
> reactimate title franProg
> = runGraphics $
> do w <- openWindowEx title (Just (0,0)) (Just (xWin,yWin))
> drawBufferedGraphic
> (us,ts,addEvents) <- windowUser w
> addEvents
> let drawPic (Just g) =
> do setGraphic w g
> quit <- addEvents
> if quit
> then return True
> else return False
> drawPic Nothing = return False
> let Event fe = sample `snapshot_` franProg
> run drawPic (fe (us,ts))
> closeWindow w
> where
> run f (x:xs) = do
> quit <- f x
> if quit
> then return ()
> else run f xs
> run f [] = return ()
>
> sample :: Event ()
> sample = Event (\(us,_) -> map aux us)
> where aux Nothing = Just ()
> aux (Just _) = Nothing
> windowUser :: Window -> IO ([Maybe UserAction], [Time], IO Bool)
> windowUser w
> = do (evs, addEv) <- makeStream
> t0 <- timeGetTime
> let addEvents =
> let loop rt = do
> mev <- maybeGetWindowEvent w
> case mev of
> Nothing -> return False
> Just e -> case e of
> Key ' ' True -> return True
> Closed -> return True
> _ -> addEv (rt, Just e) >> loop rt
> in do t <- timeGetTime
> let rt = w32ToTime (t-t0)
> quit <- loop rt
> addEv (rt, Nothing)
> return quit
> return (map snd evs, map fst evs, addEvents)
> w32ToTime t = intToFloat (fromInteger (toInteger t)) / 1000
> makeStream :: IO ([a], a -> IO ())
> makeStream = do
> ch <- newChan
> contents <- getChanContents ch
> return (contents, writeChan ch)
< Event fe =>> f = Event (map (aux f) . fe)
答案 0 :(得分:6)
<
行的要点是向您展示函数/类型的定义或替代定义。
在文件Fal.lhs
中,color1
函数有三个定义:
< color1 :: Behavior Color
< color1 = red `untilB` (lbp ->> blue)
< color1 :: Behavior Color
< color1 = red `untilB` lbp ->> blue
> color1 :: Behavior Color
> color1 = red `untilB` lbp ->> blue
ghc
和ghci
只会处理第三个问题。前两个是显示不同的尝试/替代方法来定义它。
在文件MDL.lhs
中,<
语法用于显示导入模块的定义 - 例如:
> import Haskore ( MidiFile(..), MidiChannel, ProgNum, MEvent,
> MFType, Velocity, MEvent(..), MidiEvent(..),
> MetaEvent(..), Division(..), MTempo,
> outputMidiFile )
< data MidiFile = MidiFile MFType Division [Track]
< deriving (Show, Eq)
在这种情况下,类型MidiFile
在Haskore
模块中定义并导入,<
行就是为了方便您显示定义。
在任何情况下,.lhs
和>
都会忽略ghc
文件中不以ghci
开头的任何行。