100% found this document useful (1 vote)
248 views

Haskell Programming 0.12.0 Ereader PDF

Uploaded by

Name
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
248 views

Haskell Programming 0.12.0 Ereader PDF

Uploaded by

Name
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1879

J

3FBEFS GFFECBDL
ƌ"TUPOJTIJOHMZ JOTJHIUGVM FYBNQMFT 5IJT CPPL JT B MPU MJLF
IBWJOH B HPPE UFBDIFS  JU OFWFS GBJMT UP QSPWJEF UIF MPXFOE
JOGPSNBUJPO FWFO UIPVHI * IBWF BMSFBEZ NPWFE PO 4P KVTU
MJLF B HPPE UFBDIFS JTOƊU QSFTVNQUVPVT JO XIBU *ƊN TVQQPTFE
UP LOPX XIJDI NJHIU GPSDF NF UP USZ BOE TBWF GBDF JO DBTF *
EP OPU ZFU
JOGPSNBUJPO DPOWFOJFOUMZ SFTVSGBDFTƍ Ƈ %BWJE
%FVUTDI

ƌ8IFO !IBTLFMMCPPL JT EPOF JU XJMM CF BO VOFYQFDUFE NJMF


TUPOF GPS IBTLFMM 5IFSF XJMM GPSFWFS CF )BTLFMM CFGPSF BOE
)BTLFMM BǒFSƍ Ƈ +BTPO ,VISU

ƌ* GFFM TBGF SFDPNNFOEJOH )BTLFMM UP CFHJOOFST OPX UIBU


!IBTLFMMCPPL JT BWBJMBCMF XIJDI JT WFSZ CFHJOOFSGSJFOEMZƍ Ƈ
(BCSJFM (PO[BMF[

ƌƍ4USVDUVSF BOE *OUFSQSFUBUJPO PG $PNQVUFS 1SPHSBNTƍ IBT


JUT DSFEJU CVU !IBTLFMMCPPL JT OPX NZ  SFDPNNFOEBUJPO
GPS '1 CFHJOOFSTƍ Ƈ *SJP .VTTLPQG

ƌ5IF CPPL JT MPOH CVU OPU TMPXƇB MBSHF GSBDUJPO PG JU JT


NBEF VQ PG FYBNQMFT BOE FYFSDJTFT :PV DBO UFMM JUƊT XSJUUFO
CZ TPNFPOF XIPƊT UBVHIU )BTLFMM UP QSPHSBNNFST CFGPSFƍ Ƈ
$ISJTUPQIFS +POFT
JJ

ƌ* BMSFBEZ IBWF B MPU PG FYQFSJFODF XJUI )BTLFMM CVU *ƊWF


OFWFS GFMU DPOƶEFOU JO JU UIF XBZ UIJT CPPL IBT NBEF NF GFFMƍ
Ƈ "MBJO 0Ɗ%FB

ƌ3FBM EFBM XJUI !IBTLFMMCPPL JT UIBU ZPV EPOƊU KVTU MFBSO


)BTLFMM ZPV HFU B IBOET PO FYQFSJFODF BT UP XIZ GVODUJPOBM
QSPHSBNNJOH XPSLTƍ Ƈ (FPSHF .BLSZEBLJT

ƌ0OF PG NZ HPBMT UIJT ZFBS JT UP FWBOHFMJ[F !IBTLFMMCPPL


BOE !)BTLFMM'PS.BD * UIJOL UIFTF UPPMT XJMM NBLF BOZPOF
XIP VTFT UIFN CFUUFS * XBOU UP HFU DPNGPSUBCMF XJUI JU TP UIBU
* DBO TIJǒ IPX * UIJOL BCPVU 4XJǒƍ Ƈ +BOJF $MBZUPO
$POUFOUT

3FBEFS GFFECBDL                           J

$POUFOUT JJJ
"VUIPSTƊ QSFGBDF                            YY
"DLOPXMFEHFNFOUT                         YYW
*OUSPEVDUJPO                              YYJY
8IZ 5IJT #PPL                            YYJY
" GFX XPSET UP OFX QSPHSBNNFST                YYYJW
)BTLFWBOHFMJTN                            YYYW
8IBUƊT JO UIJT CPPL                         YYYJY
#FTU QSBDUJDFT GPS FYBNQMFT BOE FYFSDJTFT           YMJJJ

 "MM :PV /FFE JT -BNCEB 


 "MM :PV /FFE JT -BNCEB                
 8IBU JT GVODUJPOBM QSPHSBNNJOH         
 8IBU JT B GVODUJPO                   
 5IF TUSVDUVSF PG MBNCEB UFSNT           
 #FUB SFEVDUJPO                      
 .VMUJQMF BSHVNFOUT                   
 &WBMVBUJPO JT TJNQMJƶDBUJPO              
 $PNCJOBUPST                       
JJJ
$0/5&/54 JW

 %JWFSHFODF                        
 4VNNBSZ                         
 $IBQUFS &YFSDJTFT                    
 "OTXFST                          
 %FƶOJUJPOT                         
 'PMMPXVQ SFTPVSDFT                  

 )FMMP )BTLFMM 
 )FMMP )BTLFMM                       
 *OUFSBDUJOH XJUI )BTLFMM DPEF            
 6OEFSTUBOEJOH FYQSFTTJPOT              
 'VODUJPOT                         
 &WBMVBUJPO                         
 *OƶY PQFSBUPST                      
 %FDMBSJOH WBMVFT                     
 "SJUINFUJD GVODUJPOT JO )BTLFMM           
 1BSFOUIFTJ[BUJPO                     
 -FU BOE XIFSF                      
 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         
 'PMMPXVQ SFTPVSDFT                  

 4USJOHT 
 1SJOUJOH TUSJOHT                      
 " ƶSTU MPPL BU UZQFT                   
 1SJOUJOH TJNQMF TUSJOHT                 
$0/5&/54 W

 5PQMFWFM WFSTVT MPDBM EFƶOJUJPOT          


 5ZQFT PG DPODBUFOBUJPO GVODUJPOT          
 $PODBUFOBUJPO BOE TDPQJOH              
 .PSF MJTU GVODUJPOT                   
 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         

 #BTJD EBUBUZQFT 


 #BTJD %BUBUZQFT                     
 8IBU BSF UZQFT                     
 "OBUPNZ PG B EBUB EFDMBSBUJPO            
 /VNFSJD UZQFT                      
 $PNQBSJOH WBMVFT                    
 (P PO BOE #PPM NF                   
 5VQMFT                           
 -JTUT                             
 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         
 /BNFT BOE WBSJBCMFT                  

 5ZQFT 
 5ZQFT                            
 8IBU BSF UZQFT GPS                   
 )PX UP SFBE UZQF TJHOBUVSFT             
 $VSSZJOH                          
 1PMZNPSQIJTN                      
$0/5&/54 WJ

 5ZQF JOGFSFODF                      


 "TTFSUJOH UZQFT GPS EFDMBSBUJPOT           
 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         
 'PMMPXVQ SFTPVSDFT                  

 5ZQFDMBTTFT 
 5ZQFDMBTTFT                        
 8IBU BSF UZQFDMBTTFT                  
 #BDL UP #PPM                       
 &R                              
 8SJUJOH UZQFDMBTT JOTUBODFT              
 /VN                             
 5ZQFEFGBVMUJOH UZQFDMBTTFT             
 0SE                             
 &OVN                            
 4IPX                            
 3FBE                             
 *OTUBODFT BSF EJTQBUDIFE CZ UZQF          
 (JNNF NPSF PQFSBUJPOT               
 $IBQUFS &YFSDJTFT                    
 $IBQUFS %FƶOJUJPOT                   
 5ZQFDMBTT JOIFSJUBODF QBSUJBM            
 'PMMPXVQ SFTPVSDFT                  

 .PSF GVODUJPOBM QBUUFSOT 


$0/5&/54 WJJ

 .BLF JU GVODZ                      


 "SHVNFOUT BOE QBSBNFUFST              
 "OPOZNPVT GVODUJPOT                 
 1BUUFSO NBUDIJOH                    
 $BTF FYQSFTTJPOT                     
 )JHIFSPSEFS GVODUJPOT                
 (VBSET                           
 'VODUJPO DPNQPTJUJPO                 
 1PJOUGSFF TUZMF                      
 %FNPOTUSBUJOH DPNQPTJUJPO             
 $IBQUFS &YFSDJTFT                    
 $IBQUFS %FƶOJUJPOT                   
 'PMMPXVQ SFTPVSDFT                  

 3FDVSTJPO 
 3FDVSTJPO                         
 'BDUPSJBM                          
 #PUUPN                           
 'JCPOBDDJ OVNCFST                   
 *OUFHSBM EJWJTJPO GSPN TDSBUDI            
 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         

 -JTUT 
 -JTUT                             
 5IF MJTU EBUBUZQF                     
$0/5&/54 WJJJ

 1BUUFSO NBUDIJOH PO MJTUT               


 -JTUƊT TZOUBDUJD TVHBS                  
 6TJOH SBOHFT UP DPOTUSVDU MJTUT            
 &YUSBDUJOH QPSUJPOT PG MJTUT              
 -JTU DPNQSFIFOTJPOT                  
 4QJOFT BOE OPOTUSJDU FWBMVBUJPO           
 5SBOTGPSNJOH MJTUT PG WBMVFT             
 'JMUFSJOH MJTUT PG WBMVFT                 
 ;JQQJOH MJTUT                        
 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         
 'PMMPXVQ SFTPVSDFT                  

 'PMEJOH MJTUT 


 'PMET                            
 #SJOHJOH ZPV JOUP UIF GPME               
 3FDVSTJWF QBUUFSOT                    
 'PME SJHIU                         
 'PME MFǒ                          
 )PX UP XSJUF GPME GVODUJPOT              
 'PMEJOH BOE FWBMVBUJPO                 
 4VNNBSZ                         
 4DBOT                            
 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         
 'PMMPXVQ SFTPVSDFT                  
$0/5&/54 JY

 "MHFCSBJD EBUBUZQFT 


 "MHFCSBJD EBUBUZQFT                   
 %BUB EFDMBSBUJPOT SFWJFX                
 %BUB BOE UZQF DPOTUSVDUPST              
 5ZQF DPOTUSVDUPST BOE LJOET             
 %BUB DPOTUSVDUPST BOE WBMVFT             
 8IBUƊT B UZQF BOE XIBUƊT EBUB            
 %BUB DPOTUSVDUPS BSJUJFT                
 8IBU NBLFT UIFTF EBUBUZQFT BMHFCSBJD      
 OFXUZQF                          
 4VN UZQFT                         
 1SPEVDU UZQFT                       
 /PSNBM GPSN                       
 $POTUSVDUJOH BOE EFDPOTUSVDUJOH WBMVFT     
 'VODUJPO UZQF JT FYQPOFOUJBM             
 )JHIFSLJOEFE EBUBUZQFT               
 -JTUT BSF QPMZNPSQIJD                 
 #JOBSZ 5SFF                        
 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         

 4JHOBMJOH BEWFSTJUZ 


 4JHOBMJOH BEWFSTJUZ                   
 )PX * MFBSOFE UP TUPQ XPSSZJOH BOE MPWF /PUIJOH
 #MFBUJOH FJUIFS                      
 ,JOET B UIPVTBOE TUBST JO ZPVS UZQFT       
$0/5&/54 Y

 $IBQUFS &YFSDJTFT                    


 %FƶOJUJPOT                         

 #VJMEJOH QSPKFDUT 


 .PEVMFT                          
 .BLJOH QBDLBHFT XJUI 4UBDL             
 8PSLJOH XJUI B CBTJD QSPKFDU             
 .BLJOH PVS QSPKFDU B MJCSBSZ             
 .PEVMF FYQPSUT                     
 .PSF PO JNQPSUJOH NPEVMFT             
 .BLJOH PVS QSPHSBN JOUFSBDUJWF          
 EP TZOUBY BOE *0                     
 )BOHNBO HBNF                     
 4UFQ 0OF *NQPSUJOH NPEVMFT            
 4UFQ 5XP (FOFSBUJOH B XPSE MJTU          
 4UFQ 5ISFF .BLJOH B QV[[MF             
 "EEJOH B OFXUZQF                    
 $IBQUFS FYFSDJTFT                    
 'PMMPXVQ SFTPVSDFT                  

 5FTUJOH 
 5FTUJOH                           
 " RVJDL UPVS PG UFTUJOH GPS UIF VOJOJUJBUFE    
 $POWFOUJPOBM UFTUJOH                  
 &OUFS 2VJDL$IFDL                    
 .PSTF DPEF                        
$0/5&/54 YJ

 ,JDLJOH BSPVOE 2VJDL$IFDL             


 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         
 'PMMPXVQ SFTPVSDFT                  

 .POPJE 4FNJHSPVQ 


 .POPJET BOE TFNJHSPVQT               
 8IBU XF UBML BCPVU XIFO XF UBML BCPVU BMHFCSBT
 .POPJE                           
 )PX .POPJE JT EFƶOFE JO )BTLFMM         
 &YBNQMFT PG VTJOH .POPJE              
 8IZ *OUFHFS EPFTOƊU IBWF B .POPJE        
 8IZ CPUIFS                       
 -BXT                             
 %JƵFSFOU JOTUBODF TBNF SFQSFTFOUBUJPO      
 3FVTJOH BMHFCSBT CZ BTLJOH GPS BMHFCSBT      
 .BEOFTT                          
 #FUUFS MJWJOH UISPVHI 2VJDL$IFDL         
 4FNJHSPVQ                         
 $IBQUFS FYFSDJTFT                    
 %FƶOJUJPOT                         
 'PMMPXVQ SFTPVSDFT                  

 'VODUPS 
 'VODUPS                           
 8IBUƊT B GVODUPS                    
$0/5&/54 YJJ

 5IFSFƊT B XIPMF MPU PG GNBQ HPJOH SPVOE     


 -FUƊT UBML BCPVU ԕ CBCZ                 
 'VODUPS -BXT                       
 5IF (PPE UIF #BE BOE UIF 6HMZ          
 $PNNPOMZ VTFE GVODUPST               
 5SBOTGPSNJOH UIF VOBQQMJFE UZQF BSHVNFOU   
 2VJDL$IFDLJOH 'VODUPS JOTUBODFT         
 &YFSDJTFT *OTUBODFT PG 'VOD             
 *HOPSJOH QPTTJCJMJUJFT                  
 " TPNFXIBU TVSQSJTJOH GVODUPS           
 .PSF TUSVDUVSF NPSF GVODUPST            
 *0 'VODUPS                         
 8IBU JG XF XBOU UP EP TPNFUIJOH EJƵFSFOU   
 'VODUPST BSF VOJRVF UP B EBUBUZQF          
 $IBQUFS FYFSDJTFT                    
 %FƶOJUJPOT                         
 'PMMPXVQ SFTPVSDFT                  

 "QQMJDBUJWF 
 "QQMJDBUJWF                        
 %FƶOJOH "QQMJDBUJWF                  
 'VODUPS WT "QQMJDBUJWF                 
 "QQMJDBUJWF GVODUPST BSF NPOPJEBM GVODUPST   
 "QQMJDBUJWF JO VTF                    
 "QQMJDBUJWF MBXT                     
 :PV LOFX UIJT XBT DPNJOH              
$0/5&/54 YJJJ

 ;JQ-JTU .POPJE                     


 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         
 'PMMPXVQ SFTPVSDFT                  

 .POBE 
 .POBE                           
 4PSSZ ƈ .POBE JT OPU B CVSSJUP           
 %P TZOUBY BOE NPOBET                 
 &YBNQMFT PG .POBE VTF                
 .POBE MBXT                        
 "QQMJDBUJPO BOE DPNQPTJUJPO            
 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPO                         
 'PMMPXVQ SFTPVSDFT                  

 "QQMZJOH TUSVDUVSF 


 "QQMJFE TUSVDUVSF                    
 .POPJE                           
 'VODUPS                           
 "QQMJDBUJWF                        
 .POBE                           
 "O FOEUPFOE FYBNQMF 63- TIPSUFOFS     
 5IBUƊT B XSBQ                       
 'PMMPXVQ SFTPVSDFT                  

 'PMEBCMF 
$0/5&/54 YJW

 'PMEBCMF                          


 5IF 'PMEBCMF DMBTT                    
 3FWFOHF PG UIF NPOPJET                
 %FNPOTUSBUJOH 'PMEBCMF JOTUBODFT         
 4PNF CBTJD EFSJWFE PQFSBUJPOT           
 $IBQUFS &YFSDJTFT                    
 'PMMPXVQ SFTPVSDFT                  

 5SBWFSTBCMF 
 5SBWFSTBCMF                        
 5IF 5SBWFSTBCMF UZQFDMBTT EFƶOJUJPO        
 TFRVFODF"                         
 USBWFSTF                           
 4P XIBUƊT USBWFSTBCMF GPS               
 .PSTF DPEF SFWJTJUFE                  
 "YJOH UFEJPVT DPEF                   
 %P BMM UIF UIJOHT                     
 5SBWFSTBCMF JOTUBODFT                  
 5SBWFSTBCMF -BXT                    
 2VBMJUZ $POUSPM                     
 $IBQUFS &YFSDJTFT                    
 'PMMPXVQ SFTPVSDFT                  

 3FBEFS 
 3FBEFS                           
 " OFX CFHJOOJOH                     
$0/5&/54 YW

 5IJT JT 3FBEFS                      


 #SFBLJOH EPXO UIF 'VODUPS PG GVODUJPOT     
 #VU VI 3FBEFS                     
 'VODUJPOT IBWF BO "QQMJDBUJWF UPP         
 5IF .POBE PG GVODUJPOT                
 3FBEFS .POBE CZ JUTFMG JT LJOEB CPSJOH      
 :PV DBO DIBOHF XIBU DPNFT CFMPX CVU OPU BCPWF
 :PV UFOE UP TFF 3FBEFS5 OPU 3FBEFS        
 $IBQUFS &YFSDJTFT                    
 'PMMPXVQ SFTPVSDFT                  

 4UBUF 
 4UBUF                             
 8IBU JT TUBUF                       
 3BOEPN OVNCFST                    
 5IF 4UBUF OFXUZQF                    
 5ISPX EPXO                       
 8SJUF 4UBUF GPS ZPVSTFMG                
 (FU B DPEJOH KPC XJUI POF XFJSE USJDL       
 $IBQUFS FYFSDJTFT                    
 'PMMPXVQ SFTPVSDFT                  

 1BSTFS DPNCJOBUPST 


 1BSTFS DPNCJOBUPST                   
 " GFX NPSF XPSET PG JOUSPEVDUJPO         
 6OEFSTUBOEJOH UIF QBSTJOH QSPDFTT         
$0/5&/54 YWJ

 1BSTJOH GSBDUJPOT                     


 )BTLFMMƊT QBSTJOH FDPTZTUFN              
 "MUFSOBUJWF                         
 1BSTJOH DPOƶHVSBUJPO ƶMFT               
 $IBSBDUFS BOE UPLFO QBSTFST             
 1PMZNPSQIJD QBSTFST                  
 .BSTIBMMJOH GSPN BO "45 UP B EBUBUZQF      
 $IBQUFS &YFSDJTFT                    
 %FƶOJUJPOT                         
 'PMMPXVQ SFTPVSDFT                  

 $PNQPTJOH UZQFT 


 $PNQPTJOH UZQFT                    
 $PNNPO GVODUJPOT BT UZQFT             
 5XP MJUUMF GVODUPST TJUUJOƊ JO B USFF
-*'5*/(                      
 5XJOQMJDBUJWF                       
 5XPOBE                          
 &YFSDJTFT $PNQPTF *OTUBODFT            
 .POBE USBOTGPSNFST                  
 *EFOUJUZ5                          
 'JOEJOH B QBUUFSO                    

 .POBE USBOTGPSNFST 


 .POBE USBOTGPSNFST                  
 .BZCF5                           
$0/5&/54 YWJJ

 &JUIFS5                           


 3FBEFS5                          
 4UBUF5                            
 5ZQFT ZPV QSPCBCMZ EPOƊU XBOU UP VTF       
 3FDPWFSJOH BO PSEJOBSZ UZQF GSPN B USBOTGPSNFS
 -FYJDBMMZ JOOFS JT TUSVDUVSBMMZ PVUFS        
 .POBE5SBOT                       
 .POBE*0 BLB [PPN[PPN              
 .POBE USBOTGPSNFST JO VTF              
 .POBET EP OPU DPNNVUF               
 5SBOTGPSN JG ZPV XBOU UP               
 $IBQUFS &YFSDJTFT                    
 'PMMPXVQ SFTPVSDFT                  

 /POTUSJDUOFTT 
 -B[JOFTT                          
 0CTFSWBUJPOBM #PUUPN 5IFPSZ            
 0VUTJEF JO JOTJEF PVU                  
 8IBU EPFT UIF PUIFS XBZ MPPL MJLF         
 $BMM CZ OBNF DBMM CZ OFFE              
 /POTUSJDU FWBMVBUJPO DIBOHFT XIBU XF DBO EP 
 5IVOL -JGF                        
 4IBSJOH JT DBSJOH                     
 3FGVUBCMF BOE JSSFGVUBCMF QBUUFSOT         
 #BOHQBUUFSOT                      
 4USJDU BOE 4USJDU%BUB                  
$0/5&/54 YWJJJ

 "EEJOH TUSJDUOFTT                     


 $IBQUFS &YFSDJTFT                    
 'PMMPXVQ SFTPVSDFT                  

 #BTJD MJCSBSJFT 


 #BTJD MJCSBSJFT BOE EBUB TUSVDUVSFT          
 #FODINBSLJOH XJUI $SJUFSJPO            
 1SPƶMJOH ZPVS QSPHSBNT                
 $POTUBOU BQQMJDBUJWF GPSNT              
 .BQ                             
 4FU                              
 4FRVFODF                          
 7FDUPS                            
 4USJOH UZQFT                        
 $IBQUFS &YFSDJTFT                    
 'PMMPXVQ SFTPVSDFT                  

 *0 
 *0                              
 8IFSF *0 FYQMBOBUJPOT HP BTUSBZ          
 5IF SFBTPO XF OFFE UIJT UZQF            
 4IBSJOH                           
 *0 EPFTOƊU EJTBCMF TIBSJOH GPS FWFSZUIJOH     
 1VSJUZ JT MPTJOH NFBOJOH                
 *0ƊT 'VODUPS "QQMJDBUJWF BOE .POBE       
 8FMM UIFO IPX EP XF .7BS             
$0/5&/54 YJY

 $IBQUFS &YFSDJTFT                    


 'PMMPXVQ SFTPVSDFT                  

 8IFO UIJOHT HP XSPOH 


 &YDFQUJPOT                         
 5IF &YDFQUJPO DMBTT BOE NFUIPET          
 5IJT NBDIJOF LJMMT QSPHSBNT             
 8BOU FJUIFS 5SZ                    
 5IF VOCFBSBCMF JNQSFDJTJPO PG USZJOH       
 8IZ UISPX*0                      
 .BLJOH PVS PXO FYDFQUJPO UZQFT          
 4VSQSJTJOH JOUFSBDUJPO XJUI CPUUPN         
 "TZODISPOPVT &YDFQUJPOT               
 'PMMPXVQ 3FBEJOH                   

 'JOBM QSPKFDU 


 'JOBM QSPKFDU                        
 ƶOHFSE                           
 &YQMPSJOH ƶOHFS                     
 4MJHIUMZ NPEFSOJ[FE ƶOHFSE             
 $IBQUFS &YFSDJTFT                    
$0/5&/54 YY

"VUIPSTƊ QSFGBDF
$ISJTƊT TUPSZ
*ƊWF CFFO QSPHSBNNJOH GPS PWFS  ZFBST  PG UIFN QSPGFT
TJPOBMMZ *ƊWF XPSLFE QSJNBSJMZ JO $PNNPO -JTQ $MPKVSF BOE
1ZUIPO * CFDBNF JOUFSFTUFE JO )BTLFMM BCPVU  ZFBST BHP
)BTLFMM XBT UIF MBOHVBHF UIBU NBEF NF BXBSF UIBU QSPHSFTT
JT CFJOH NBEF JO QSPHSBNNJOH MBOHVBHF SFTFBSDI BOE UIBU
UIFSF BSF CFOFƶUT UP VTJOH B MBOHVBHF XJUI B EFTJHO JOGPSNFE
CZ LOPXMFEHF PG UIPTF BEWBODFNFOUT
*ƊWF IBE UZQF FSSPST JO $MPKVSF UIBU NVMUJQMF QSPGFTTJPOBM
$MPKVSF EFWT JODMVEJOH NZTFMG
DPVMEOƊU SFTPMWF JO MFTT UIBO
 IPVST CFDBVTF PG UIF TPVSDFUPTJOL EJTUBODF DBVTFE CZ EZ
OBNJD UZQJOH 8F IBE DPQJPVT UFTUT 8F BEEFE printlnT FW
FSZXIFSF 8F UFTUFE JOEJWJEVBM GVODUJPOT GSPN UIF 3&1- *U
TUJMM UPPL BHFT *U XBT POMZ  MJOFT PG $MPKVSF * EJE ƶOBMMZ
ƶY JU BOE GPVOE JU XBT EVF UP WFDUPST JO $MPKVSF JNQMFNFOUJOH
IFn 5IF DSB[Z WBMVFT UIBU QSPQBHBUFE GSPN UIF IFn VTBHF PG
UIF WFDUPS BMMPXFE NBMGPSNFE EBUB UP QSPQBHBUF EPXOXBSE
GBS BXBZ GSPN UIF PSJHJO PG UIF QSPCMFN *ƊWF IBE TJNJMBS IBQ
QFO JO 1ZUIPO BOE $PNNPO -JTQ BT XFMM 5IF TBNF JTTVF
JO )BTLFMM XPVME CF USJWJBMMZ SFTPMWFE JO B NJOVUF PS MFTT CF
DBVTF UIF UZQFDIFDLFS XJMM JEFOUJGZ QSFDJTFMZ XIFSF ZPV XFSF
JODPOTJTUFOU
* VTF )BTLFMM CFDBVTF * XBOU UP CF BCMF UP SFGBDUPS XJUIPVU
$0/5&/54 YYJ

GFBS CFDBVTF * XBOU NBJOUFOBODF UP CF TPNFUIJOH * EPOƊU SF


TFOU TP * DBO SFVTF DPEF GSFFMZ 5IJT EPFTOƊU DPNF XJUIPVU
MFBSOJOH OFX UIJOHT 5IF EJƵFSFODF CFUXFFO QFPQMF UIBU BSF
ƌHPPE BU NBUIƍ XIP ƌEP JU JO UIFJS IFBEƍ BOE QSPGFTTJPOBM NBUI
FNBUJDJBOT JT UIBU UIF MBUUFS TIPX UIFJS XPSL BOE VTF UPPMT UIBU
IFMQ UIFN HFU UIF KPC EPOF 8IFO ZPVƊSF VTJOH B EZOBNJDBMMZ
UZQFE MBOHVBHF ZPVƊSF GPSDJOH ZPVSTFMG VOOFDFTTBSJMZ UP EP JU
ƌJO ZPVS IFBEƍ "T B IVNBO XJUI MJNJUFE XPSLJOH NFNPSZ *
XBOU BMM UIF IFMQ * DBO HFU UP SFBTPO BCPVU BOE XSJUF DPSSFDU
DPEF )BTLFMM QSPWJEFT UIBU IFMQ
)BTLFMM JT OPU B EJƸDVMU MBOHVBHF UP VTF ƈ RVJUF UIF PQQPTJUF
*ƊN OPX BCMF UP UBDLMF QSPCMFNT UIBU * DPVMEOƊU IBWF UBDLMFE
XIFO * XBT QSJNBSJMZ B $MPKVSF $PNNPO -JTQ PS 1ZUIPO
VTFS )BTLFMM JT EJƸDVMU UP UFBDI FƵFDUJWFMZ BOE UIF JOFƵFDUJWF
QFEBHPHZ IBT NBEF JU IBSE GPS NBOZ QFPQMF UP MFBSO
*U EPFTOƊU IBWF UP CF UIBU XBZ
*ƊWF TQFOU UIF MBTU UXP ZFBST BDUJWFMZ UFBDIJOH )BTLFMM PO
MJOF BOE JO QFSTPO "MPOH UIF XBZ * TUBSUFE LFFQJOH OPUFT
PO FYFSDJTFT BOE NFUIPET PG UFBDIJOH TQFDJƶD DPODFQUT BOE
UFDIOJRVFT UIBU XPSLFE 5IPTF OPUFT FWFOUVBMMZ UVSOFE JOUP
NZ HVJEF GPS MFBSOJOH )BTLFMM *ƊN TUJMM MFBSOJOH IPX UP UFBDI
)BTLFMM CFUUFS CZ XPSLJOH XJUI QFPQMF MPDBMMZ JO "VTUJO 5FYBT
BT XFMM BT POMJOF JO UIF *3$ DIBOOFM * NBEF GPS CFHJOOFST UP
HFU IFMQ XJUI MFBSOJOH )BTLFMM
* XSPUF UIJT CPPL CFDBVTF * IBE B IBSE UJNF MFBSOJOH )BTLFMM
BOE * EPOƊU XBOU PUIFST UP TUSVHHMF UIF XBZ * EJE
$0/5&/54 YYJJ

+VMJFƊT TUPSZ
* NFU $ISJT "MMFO JO TQSJOH  8F NFU PO 5XJUUFS BOE
RVJDLMZ CFDBNF GSJFOET "T BOZPOF XIP IBT FODPVOUFSFE
$ISJT ƈ QSPCBCMZ JO BOZ NFEJVN CVU DFSUBJOMZ PO 5XJUUFS ƈ
LOPXT JU EPFTOƊU UBLF MPOH CFGPSF IF TUBSUT VSHJOH ZPV UP MFBSO
)BTLFMM
* UPME IJN * IBE OP JOUFSFTU JO QSPHSBNNJOH * UPME IJN
OPUIJOH BOE OPCPEZ IBE FWFS CFFO BCMF UP JOUFSFTU NF JO QSP
HSBNNJOH CFGPSF 8IFO $ISJT MFBSOFE PG NZ CBDLHSPVOE
JO MJOHVJTUJDT IF UIPVHIU * NJHIU CF JOUFSFTUFE JO OBUVSBM MBO
HVBHF QSPDFTTJOH BOE FYIPSUFE NF UP MFBSO )BTLFMM GPS UIBU
QVSQPTF * SFNBJOFE VODPOWJODFE
5IFO IF USJFE B EJƵFSFOU BQQSPBDI )F XBT TQFOEJOH B MPU PG
UJNF HBUIFSJOH BOE FWBMVBUJOH SFTPVSDFT GPS UFBDIJOH )BTLFMM
BOE SFƶOJOH IJT QFEBHPHJDBM UFDIOJRVFT BOE IF DPOWJODFE NF
UP USZ UP MFBSO )BTLFMM TP UIBU IF DPVME HBJO UIF FYQFSJFODF
PG UFBDIJOH B DPEFOFPQIZUF 'JOBMMZ XJUI BO ƌBOZUIJOH GPS
TDJFODFƍ BUUJUVEF * HBWF JO
$ISJT IBE BMSFBEZ LOPXO UIBU UIF BWBJMBCMF )BTLFMM MFBSOJOH
NBUFSJBMT FBDI IBE QSPCMFNT CVU * EPOƊU UIJOL FWFO IF SFBMJ[FE
KVTU IPX GSVTUSBUJOH UIFZ XPVME CF UP NF "MM PG UIF NBUFSJBMT
* SBO BDSPTT SFMJFE PO B CBDLHSPVOE XJUI PUIFS QSPHSBNNJOH
MBOHVBHFT BOE MFǒ NBOZ UFSNT VOEFƶOFE PS FYQMBJOFE GFB
UVSFT PG )BTLFMM CZ BOBMPHZ PǒFO GBVMUZ
UP GFBUVSFT PG PUIFS
MBOHVBHFT ƈ GFBUVSFT * IBE OP FYQFSJFODF XJUI
$0/5&/54 YYJJJ

8IFO * TBZ * IBE OP QSPHSBNNJOH FYQFSJFODF * SFBMMZ USVMZ


NFBO JU * IBE UP TUBSU GSPN MFBSOJOH XIBU B DPNQJMFS EPFT
XIBU WFSTJPO DPOUSPM NFBOT XIBU DPOTUJUVUFT TJEF FƵFDUT XIBU
JT B MJCSBSZ XIBU JT B NPEVMF XIBU PO FBSUI JT B TUBDL PWFSƷPX
"U UIF UJNF PG UIJT XSJUJOH UIBU JT XIFSF * XBT MFTT UIBO B ZFBS
BHP CZ UIF UJNF XF ƶOJTI XSJUJOH UIJT CPPL BOE JU JT QVCMJTIFE
JU XJMM CF BMNPTU UXP ZFBST
* EJEOƊU UIJOL * XPVME TUJDL XJUI JU *U XBT UPP GSVTUSBUJOH UPP
UJNFDPOTVNJOH BOE * TBX OP QSBDUJDBM QVSQPTF JO JU BOZXBZ
* GFMU MJLF * XPVMEOƊU CF BCMF UP MFBSO JU 8PSLJOH XJUI $ISJT
LFQU NF NPUJWBUFE BOE JOUFSFTUFE UIPVHI
&WFOUVBMMZ BT IF SFBMJ[FE UIBU B OFX UZQF PG CPPL GPS MFBSO
JOH )BTLFMM XBT OFDFTTBSZ IF EFDJEFE UP XSJUF POF * BHSFFE BU
UIF UJNF UP CF IJT HVJOFB QJH )F XPVME TFOE NF DIBQUFST BOE
* XPVME MFBSO )BTLFMM GSPN UIFN BOE TFOE GFFECBDL 5ISPVHI
UIF GBMM XF XPSLFE MJLF UIJT PO BOE PƵ JO TIPSU CVSTUT &WFO
UVBMMZ XF GPVOE JU NPSF FƸDJFOU GPS NF UP UBLF PO BVUIPSTIJQ
EVUJFT 8F EFWFMPQFE B XSJUJOH QSPDFTT XIFSF $ISJT NBEF
UIF ƶSTU QBTT BU B DIBQUFS TDBƵPMEJOH UIF NBUFSJBM JU OFFEFE UP
DPWFS 5IFO * ƶMMFE JO UIF QBSUT UIBU * VOEFSTUPPE BOE DBNF
VQ XJUI RVFTUJPOT UIBU XPVME FMBCPSBUF BOE DMBSJGZ UIF QBSUT *
EJEOƊU BMSFBEZ LOPX )F BOTXFSFE NZ RVFTUJPOT VOUJM * VOEFS
TUPPE BOE * DPOUJOVFE BEEJOH UP BOE SFƶOJOH XIBU XBT UIFSF
8F FBDI XSPUF FYFSDJTFT ƈ * XSJUF NVDI FBTJFS POFT UIBO IF
EPFT CVU UIF WBSJFUZ JT CFOFƶDJBM
* IBWF USJFE UISPVHIPVU UIF QSPDFTT UP LFFQ UIJOLJOH GSPN
$0/5&/54 YYJW

UIF QFSTQFDUJWF PG UIF BCTPMVUF CFHJOOFS 'PS POF UIJOH *


XBOUFE NZ PXO VOEFSTUBOEJOH PG )BTLFMM UP EFFQFO BT * XSPUF
TP * LFQU RVFTUJPOJOH UIF UIJOHT * UIPVHIU * LOFX "MTP * XBOUFE
UIJT CPPL UP CF BDDFTTJCMF UP FWFSZPOF
*O JOUFSBDUJOH XJUI PUIFS )BTLFMM MFBSOFST * PǒFO IFBS UIBU
PUIFS NBUFSJBMT MFBWF UIFN GFFMJOH MJLF )BTLFMM JT EJƸDVMU BOE
NZTUFSJPVT B QSPHSBNNJOH MBOHVBHF CFTU MFǒ UP XJ[BSET
*U EPFTOƊU IBWF UP CF UIBU XBZ
$0/5&/54 YYW

"DLOPXMFEHFNFOUT
5IJT CPPL EFWFMPQFE PVU PG NBOZ FƵPSUT UP UFBDI BOE MFBSO
)BTLFMM POMJOF BOE PƵ 8F DPVME OPU IBWF EPOF UIJT XJUIPVU
UIF IFMQ PG UIF HSPXJOH DPNNVOJUZ PG GSJFOEMZ )BTLFMMFST BT
XFMM BT UIF )BTLFMM MFBSOFST XIP IBWF HSBDJPVTMZ PƵFSFE UJNF
UP IFMQ VT NBLF UIF CPPL CFUUFS
'JSTU BOE GPSFNPTU XF PXF B IVHF EFCU PG HSBUJUVEF UP PVS
ƶSTUSPVOE SFWJFXFST "OHFMB .BZ 0Ɗ$POOPS BOE .BSUJO 7ML
GPS UIFJS USFNFOEPVT QBUJFODF 8F IBWF TFOU UIFN FBDI TPNF
WFSZ SPVHI NBUFSJBM BOE UIFZ IBWF CFFO XJMMJOH UP XPSL XJUI
JU BOE TFOE EFUBJMFE GFFECBDL BCPVU XIBU XPSLFE BOE XIBU
EJEOƊU 5IFJS SFWJFXT IFMQFE FOTVSF UIF CPPL JT TVJUBCMF GPS
CPUI CFHJOOFST BOE DPNQSFIFOTJWF "MTP UIFZƊSF CPUI KVTU
XPOEFSGVM QFPQMF BMM BSPVOE
.BSUJO %F.FMMP %BOJFM (FF BOE 4JNPO :BOH IBWF FBDI
TFOU VT NBOZ
TNBSU DSJUJDJTNT BOE IFMQGVM TVHHFTUJPOT 5IF
CPPL XPVME IBWF CFFO TIPSUFS XJUIPVU UIFJS IFMQ XF UIJOL
CVU JUƊT NVDI NPSF UIPSPVHI BOE DMFBS OPX
" OVNCFS PG QFPQMF IBWF DPOUSJCVUFE GFFECBDL BOE UFDI
OJDBM SFWJFX GPS MJNJUFE QBSUT PG UIF CPPL 5IBOLT UP 4FBO
$IBMNFST &SJL EF $BTUSP -PQP "MQ .FTUBOPHVMMBSJ +VBO "M
CFSUP 4BODIF[ +POBUIBO 'FSHVTPO %FCPSBI /FXUPO .BUU
1BSTPOT 1FUFS )BSQFOEJOH +PTI $BSUXSJHIU &SJD .FSUFOT
BOE (FPSHF .BLSZEBLJT XIP IBWF BMM PƵFSFE DSJUJRVFT PG PVS
XSJUJOH BOE PVS UFDIOJDBM DPWFSBHF PG EJƵFSFOU UPQJDT
$0/5&/54 YYWJ

8F IBWF TPNF WFSZ BDUJWF FBSMZ BDDFTT SFBEFST XIP TFOE VT


B TUSFBN PG GFFECBDL FWFSZUIJOH GSPN NJOPS UZQPHSBQIJDBM
FSSPST UIFZ ƶOE UP RVFTUJPOT BCPVU FYFSDJTFT BOE XFƊSF QMFBTFE
BOE HSBUFGVM UP IBWF UIFJS JOQVU 5IF CPPL XPVME CF NFTTJFS
BOE UIF FYFSDJTFT MFTT VTFGVM JG OPU GPS UIFJS IFMQ +VMJFO #BMFZ
BOE +BTPO 3PTF,VISU IBWF CFFO QBSUJDVMBSMZ PVUTUBOEJOH PO
UIJT GSPOU OPU POMZ SFQSFTFOUJOH B OPOUSJWJBM QPSUJPO PG PVS
SFBEFS GFFECBDL PWFS UIF DPVSTF PG TFWFSBM SFMFBTFT PG UIF CPPL
CVU BMTP DBUDIJOH UIJOHT OPCPEZ FMTF OPUJDFE
5IF CPPL DPWFS XBT EFTJHOFE CZ %BWJE %FVUTDI TLPSF@EF
PO 5XJUUFS
 )F UPPL QJUZ PO UIF TUBUF PG PVS QSFWJPVT PSJHJOBM
TVQFS TQFDJBM FBSMZ BDDFTT DPWFS BOE UPPL JU VQPO IJNTFMG UP
SFEFTJHO JU 8F MJLFE JU TP NVDI XF BTLFE IJN UP SFEP UIF CPPL
XFC TJUF BT XFMM )FƊT B UBMFOUFE EFTJHOFS BOE XFƊSF HSBUFGVM
GPS BMM UIF XPSL IFƊT EPOF GPS VT
" TQFDJBM UIBOLZPV JT PXFE UP 4PSZV .PSPOVLJ +VMJFƊT TPO
XIP BHSFFE UP USZ UP VTF UIF CPPL UP UFBDI IJNTFMG )BTLFMM BOE
BMMPXFE VT UP VTF IJT GFFECBDL BOE PDDBTJPOBMMZ CMPH BCPVU IJT
QSPHSFTT
" XBSN IFMMP UP BMM UIF SFBEJOH HSPVQT CPUI POMJOF BOE
JO NFBUTQBDF UIBU IBWF GPSNFE UP XPSL UISPVHI UIF CPPL
UPHFUIFS 8FƊWF IBE TPNF HSFBU GFFECBDL GSPN UIFTF HSPVQT
BOE IPQF UP WJTJU XJUI ZPV BMM TPNFEBZ 8FƊSF EFMJHIUFE UP TFF
UIF )BTLFMM DPNNVOJUZ HSPXJOH
8F XPVME BMTP MJLF UP UIBOL .JDIBFM /FBMF GPS CFJOH GVOOZ
BOE MFUUJOH VT VTF TPNFUIJOH IF TBJE PO 5XJUUFS BT BO FQJHSBQI
$0/5&/54 YYWJJ

4PNF EBZ XF IPQF UP CVZ UIF HFOUMFNBO B CFFS


5IBOL ZPV BT XFMM UP 4UFWFO 1SPDUPS GPS IBWJOH IPTUFE VT PO
IJT 'VODUJPOBM (FFLFSZ QPEDBTU BOE UP "EBN 4UBDPWJBL BOE
+FSPE 4BOUP GPS JOWJUJOH VT POUP UIFJS QPEDBTU 5IF $IBOHFMPH
ƈ BOE UP ;BLJ .BOJBO GPS CSJOHJOH VT UP "EBN BOE +FSPEƊT
BUUFOUJPO

$ISJT * XPVME MJLF UP UIBOL UIF QBSUJDJQBOUT JO UIF #haskell-


beginners *3$ DIBOOFM UIF UFBDIFST BOE UIF TUVEFOUT XIP IBWF
IFMQFE NF QSBDUJDF BOE SFƶOF NZ UFBDIJOH UFDIOJRVFT .BOZ
PG UIF FYFSDJTFT BOE BQQSPBDIFT JO UIF CPPL XPVMEƊWF OFWFS
IBQQFOFE XJUIPVU UIF XPOEFSGVM )BTLFMM *3$ DPNNVOJUZ UP
MFBSO GSPN
* PXF "MFY ,VSJMJO $BSUFS 4DIPOXBME "JEBO $PZOF BOE
.BSL 8PUUPO UIBOLT GPS CFJOH UIFSF XIFO * XBT SFBMMZ CBE BU
UFBDIJOH CFJOH LJOE BOE QBUJFOU GSJFOET BOE GPS HJWJOH NF
BEWJDF XIFO * OFFEFE JU * XPVMEOƊU IBWF TDSBUDIFE UIJT JUDI
XJUIPVU ZƊBMM

+VMJF * XPVME MJLF UP TFOE B TQFDJBM TIPVUPVU UP UIF "VTUJO


)BTLFMM NFFUVQ HSPVQ FTQFDJBMMZ %BO -JFO BOE UP UIF )BTLFMM
5XJUUFS DPNNVOJUZ GPS NBLJOH NF GFFM XFMDPNF 5IF MJTU PG
)BTLFMMFST XIP IBWF SFTQPOEFE UP UIF LWFUDIFT BOE DPOGVTJPOT
PG B )BTLFMM CFHJOOFS XJUI IFMQ IVNPS BOE BEWJDF XPVME CF
WFSZ MPOH JOEFFE
$0/5&/54 YYWJJJ

.Z IVTCBOE BOE DIJMESFO IBWF UPMFSBUFE NF TQFOEJOH VO


DPVOUBCMF IPVST JNNFSTFE JO UIF EBSL BSUT PG UIVOLFSZ * BN
HSBUFGVM GPS UIFJS MPWF QBUJFODF BOE TVQQPSU BOE IPQF UIBU
NZ LJET XJMM SFNFNCFS UIJT UIBU JUƊT OFWFS UPP MBUF UP MFBSO
TPNFUIJOH OFX #FTPT NJKPT
'JOBMMZ B XBSN UIBOLZPV UP PVS GSJFOE (FPSHF .BLSZEBLJT
GPS UIF POHPJOH EJTQFOTBUJPO PG XJTEPN PO NBUUFST UP EP XJUI
NBUI QSPHSBNNJOH UIF XFJSEJOH XBZ BOE MJGF
"OZ FSSPST JO UIF CPPL PG DPVSTF SFNBJO UIF TPMF SFTQPOTJ
CJMJUZ PG UIF BVUIPST
$0/5&/54 YYJY

*OUSPEVDUJPO
8FMDPNF UP B OFX XBZ UP MFBSO )BTLFMM 1FSIBQT ZPV BSF
DPNJOH UP UIJT CPPL GSVTUSBUFE CZ QSFWJPVT BUUFNQUT UP MFBSO
)BTLFMM 1FSIBQT ZPV IBWF POMZ UIF GBJOUFTU OPUJPO PG XIBU
)BTLFMM JT 1FSIBQT ZPV BSF DPNJOH IFSF CFDBVTF ZPV BSF OPU
DPOWJODFE UIBU BOZUIJOH XJMM FWFS CF CFUUFS UIBO $PNNPO
-JTQ4DBMB3VCZXIBUFWFS MBOHVBHF ZPV MPWF BOE ZPV XBOU
UP BSHVF XJUI VT 1FSIBQT ZPV XFSF KVTU MPPLJOH GPS UIF 
CJMMJPOUI OC UIJT OVNCFS NBZ CF JOBDDVSBUF
NPOBE UVUPSJBM
DFSUBJO UIBU UIJT UJNF BSPVOE ZPV XJMM VOEFSTUBOE NPOBET
PODF BOE GPS BMM 8IBUFWFS ZPVS TJUVBUJPO XFMDPNF BOE SFBE
PO *U JT PVS HPBM IFSF UP NBLF )BTLFMM BT DMFBS QBJOMFTT BOE
QSBDUJDBM BT XF DBO OP NBUUFS XIBU QSJPS FYQFSJFODFT ZPVƊSF
CSJOHJOH UP UIF UBCMF

8IZ 5IJT #PPL


*G ZPV BSF OFX UP QSPHSBNNJOH FOUJSFMZ )BTLFMM JT B HSFBU
ƶSTU MBOHVBHF )BTLFMM JT B HFOFSBM QVSQPTF GVODUJPOBM QSP
HSBNNJOH MBOHVBHF *UƊT BQQMJDBCMF WJSUVBMMZ BOZXIFSF POF
XPVME VTF B QSPHSBN UP TPMWF B QSPCMFN TBWF GPS TPNF TQFDJƶD
FNCFEEFE BQQMJDBUJPOT *G ZPV DPVME XSJUF TPǒXBSF UP TPMWF B

'VODUJPOBM QSPHSBNNJOH JT B TUZMF PG QSPHSBNNJOH JO XIJDI GVODUJPO DBMMT SBUIFS
UIBO B TFSJFT PG JOTUSVDUJPOT GPS UIF DPNQVUFS UP FYFDVUF BSF UIF QSJNBSZ DPOTUSVDUT PG
ZPVS QSPHSBN 8IBU JU JT EPFTOƊU NBUUFS NVDI SJHIU OPX )BTLFMM DPNQMFUFMZ FNCPEJFT
UIF GVODUJPOBM TUZMF TP JU XJMM CFDPNF DMFBS PWFS UIF DPVSTF PG UIF CPPL
$0/5&/54 YYY

QSPCMFN ZPV DPVME QSPCBCMZ VTF )BTLFMM


*G ZPV BSF BMSFBEZ B QSPHSBNNFS ZPV NBZ CF MPPLJOH UP
FOSJDI ZPVS TLJMMT CZ MFBSOJOH )BTLFMM GPS B WBSJFUZ PG SFBTPOT
ƈ GSPN MPWF PG QVSF GVODUJPOBM QSPHSBNNJOH JUTFMG UP XBOUJOH
UP XSJUF GVODUJPOBM 4DBMB DPEF UP ƶOEJOH B CSJEHF UP 1VSF4DSJQU
PS *ESJT -BOHVBHFT TVDI BT +BWB BSF HSBEVBMMZ BEPQUJOH GVOD
UJPOBM DPODFQUT CVU NPTU XFSF OPU EFTJHOFE UP CF GVODUJPOBM
MBOHVBHFT #FDBVTF )BTLFMM JT B QVSF GVODUJPOBM MBOHVBHF JU JT
B GFSUJMF FOWJSPONFOU GPS NBTUFSJOH GVODUJPOBM QSPHSBNNJOH
5IBU XBZ PG UIJOLJOH BOE QSPCMFN TPMWJOH JT VTFGVM OP NBUUFS
XIBU PUIFS MBOHVBHFT ZPV NJHIU LOPX PS MFBSO 8FƊWF IFBSE
GSPN SFBEFST XIP BSF ƶOEJOH UIJT CPPL VTFGVM UP UIFJS XPSL JO
EJWFSTF MBOHVBHFT TVDI BT 4DBMB ' 'SFHF 4XJǒ 1VSF4DSJQU
*ESJT BOE &MN
)BTLFMM IBT B CJU PG B SFQVUBUJPO GPS CFJOH EJƸDVMU 8SJUJOH
)BTLFMM NBZ TFFN UP CF NPSF EJƸDVMU VQ GSPOU OPU KVTU CFDBVTF
PG UIF IBTTMF PG MFBSOJOH B MBOHVBHF UIBU JT TZOUBDUJDBMMZ BOE
DPODFQUVBMMZ EJƵFSFOU GSPN B MBOHVBHF ZPV BMSFBEZ LOPX CVU
BMTP CFDBVTF PG GFBUVSFT TVDI BT TUSPOH UZQJOH UIBU FOGPSDF
TPNF EJTDJQMJOF JO IPX ZPV XSJUF ZPVS DPEF #VU XIBU TFFNT
MJLF B CVH JT B GFBUVSF )VNBOT VOGPSUVOBUFMZ IBWF SFMBUJWFMZ
MJNJUFE BCJMJUJFT PG TIPSUUFSN NFNPSZ BOE DPODFOUSBUJPO
FWFO JG XF EPOƊU MJLF UP BENJU JU 8F DBOOPU USBDL BMM SFMFWBOU
NFUBEBUB BCPVU PVS QSPHSBNT JO PVS IFBET 6TJOH VQ XPSLJOH
NFNPSZ GPS BOZUIJOH B DPNQVUFS DBO EP GPS VT JT DPVOUFS
QSPEVDUJWF BOE DPNQVUFST BSF WFSZ HPPE BU LFFQJOH USBDL PG
$0/5&/54 YYYJ

EBUB GPS VT JODMVEJOH NFUBEBUB TVDI BT UZQFT


8F EPOƊU XSJUF )BTLFMM CFDBVTF XFƊSF HFOJVTFT ƈ XF VTF
UPPMT MJLF )BTLFMM CFDBVTF XFƊSF OPU HFOJVTFT BOE UIFZ IFMQ VT
(PPE UPPMT MJLF )BTLFMM FOBCMF VT UP XPSL GBTUFS NBLF GFXFS
NJTUBLFT BOE IBWF NPSF JOGPSNBUJPO BCPVU XIBU PVS DPEF JT
TVQQPTFE UP EP BT XF SFBE JU
8F VTF )BTLFMM CFDBVTF JU JT FBTJFS PWFS UIF MPOH SVO
BOE FOBCMFT
VT UP EP B CFUUFS KPC 5IBUƊT JU 5IFSFƊT B SBNQVQ SFRVJSFE JO
PSEFS UP HFU TUBSUFE CVU UIBU DBO CF BNFMJPSBUFE XJUI QBUJFODF
BOE B XJMMJOHOFTT UP XPSL UISPVHI FYFSDJTFT

0, CVU * XBT KVTU MPPLJOH GPS B NPOBE UVUPSJBM


5IF CBE OFXT JT MPPLJOH GPS BO FBTZ SPVUF JOUP )BTLFMM BOE
GVODUJPOBM QSPHSBNNJOH JT IPX B MPU PG QFPQMF FOE VQ UIJOL
JOH JUƊT ƌUPP IBSEƍ GPS UIFN 5IF HPPE OFXT JT XF IBWF B MPU
PG FYQFSJFODF UFBDIJOH BOE XF EPOƊU XBOU UIBU UP IBQQFO UP
BOZPOF CVU FTQFDJBMMZ OPU ZPV HFOUMF SFBEFS
8F FODPVSBHF ZPV UP GPSHFU XIBU ZPV NJHIU BMSFBEZ LOPX
BCPVU QSPHSBNNJOH BOE DPNF BU UIJT DPVSTF JO )BTLFMM XJUI B
CFHJOOFSƊT NJOETFU .BLF ZPVSTFMG BO FNQUZ WFTTFM SFBEZ UP
MFU UIF UZQFT ƷPX UISPVHI ZPV
*G ZPV BSF BO FYQFSJFODFE QSPHSBNNFS MFBSOJOH )BTLFMM JT
NPSF MJLF MFBSOJOH UP QSPHSBN BMM PWFS BHBJO -FBSOJOH )BTLFMM
JNQPTFT OFX XBZT PG UIJOLJOH BCPVU BOE TUSVDUVSJOH QSPHSBNT
PO NPTU QFPQMF BMSFBEZ DPNGPSUBCMF XJUI BO JNQFSBUJWF PS
$0/5&/54 YYYJJ

VOUZQFE QSPHSBNNJOH MBOHVBHF 5IJT NBLFT JU IBSEFS UP


MFBSO OPU CFDBVTF JU JT JOUSJOTJDBMMZ IBSEFS CVU CFDBVTF NPTU
QFPQMF XIP IBWF MFBSOFE BU MFBTU B DPVQMF PG QSPHSBNNJOH
MBOHVBHFT BSF BDDVTUPNFE UP UIF QSPDFTT CFJOH USJWJBM BOE
UIFJS FYQFDUBUJPOT IBWF CFFO TFU JO B XBZ UIBU MFOET JUTFMG UP
CVSOPVU BOE GBJMVSF
*G )BTLFMM JT ZPVS ƶSTU MBOHVBHF PS FWFO JG JU JT OPU ZPV NBZ
IBWF OPUJDFE B TQFDJƶD QSPCMFN XJUI NBOZ )BTLFMM MFBSOJOH
SFTPVSDFT UIFZ BTTVNF B DFSUBJO MFWFM PG CBDLHSPVOE XJUI
QSPHSBNNJOH TP UIFZ GSFRVFOUMZ FYQMBJO )BTLFMM DPODFQUT JO
UFSNT CZ BOBMPHZ PS CZ DPOUSBTU PG QSPHSBNNJOH DPODFQUT
GSPN PUIFS MBOHVBHFT 5IJT JT DPOGVTJOH GPS UIF TUVEFOU XIP
EPFTOƊU LOPX UIPTF PUIFS MBOHVBHFT CVU XF QPTJU UIBU JU JT KVTU
BT VOIFMQGVM GPS FYQFSJFODFE QSPHSBNNFST .PTU BUUFNQUT UP
DPNQBSF )BTLFMM XJUI PUIFS MBOHVBHFT POMZ MFBE UP B TVQFSƶDJBM
VOEFSTUBOEJOH PG )BTLFMM BOE NBLJOH BOBMPHJFT UP MPPQT BOE
PUIFS TVDI DPOTUSVDUT DBO MFBE UP CBE JOUVJUJPOT BCPVU IPX
)BTLFMM DPEF XPSLT 'PS BMM PG UIFTF SFBTPOT XF IBWF USJFE UP
BWPJE SFMZJOH PO LOPXMFEHF PG PUIFS QSPHSBNNJOH MBOHVBHFT
+VTU BT ZPV DBOƊU BDIJFWF ƷVFODZ JO B IVNBO MBOHVBHF TP MPOH
BT ZPV BSF TUJMM BUUFNQUJOH EJSFDU USBOTMBUJPOT PG DPODFQUT BOE
TUSVDUVSFT GSPN ZPVS OBUJWF MBOHVBHF UP UIF UBSHFU MBOHVBHF
JUƊT CFTU UP MFBSO UP VOEFSTUBOE )BTLFMM PO JUT PXO UFSNT
$0/5&/54 YYYJJJ

#VU *ƊWF IFBSE )BTLFMM JT IBSE


5IFSFƊT B XJME SVNPS UIBU HPFT BSPVOE UIF JOUFSOFU GSPN UJNF
UP UJNF BCPVU OFFEJOH B 1I% JO NBUIFNBUJDT BOE BO VOEFS
TUBOEJOH PG NPOBET KVTU UP XSJUF ƌIFMMP XPSMEƍ JO )BTLFMM
8F XJMM XSJUF ƌIFMMP XPSMEƍ JO $IBQUFS  8FƊSF HPJOH UP EP
TPNF BSJUINFUJD CFGPSF UIBU UP HFU ZPV VTFE UP GVODUJPO TZOUBY
BOE BQQMJDBUJPO JO )BTLFMM CVU ZPV XJMM OPU OFFE B 1I% JO
NPOBEPMPHZ UP XSJUF JU
*O USVUI UIFSF XJMM CF B NPOBE VOEFSMZJOH PVS ƌIFMMP XPSME ƍ
BOE CZ UIF FOE PG UIF CPPL ZPV XJMM VOEFSTUBOE NPOBET
CVU ZPVƊMM CF JOUFSBDUJOH XJUI NPOBEJD DPEF MPOH CFGPSF ZPV
VOEFSTUBOE IPX JU BMM XPSLT :PVƊMM ƶOE BU UJNFT UIJT CPPL
HPFT JOUP NPSF EFUBJM UIBO ZPV TUSJDUMZ OFFE UP CF BCMF UP XSJUF
)BTLFMM TVDDFTTGVMMZ 5IFSF JT OP QSPCMFN XJUI UIBU :PV EP
OPU OFFE UP VOEFSTUBOE FWFSZUIJOH JO IFSF QFSGFDUMZ PO UIF
ƶSTU USZ
:PV BSF OPU B 4QBSUBO XBSSJPS XIP NVTU DPNF CBDL XJUI
ZPVS TIJFME PS PO JU 3FUVSOJOH MBUFS UP JOWFTUJHBUF UIJOHT NPSF
EFFQMZ JT BO FƸDJFOU UFDIOJRVF OPU B GBJMVSF

8SJUJOH ƌIFMMP XPSMEƍ JO B OFX QSPHSBNNJOH MBOHVBHF JT B TUBOEBSE TPSU PG ƌCBCZƊT
ƶSTU QSPHSBN ƍ TP UIF JEFB IFSF JT UIBU JG JUƊT EJƸDVMU UP XSJUF B ƌIFMMP XPSMEƍ QSPHSBN
UIFO UIF MBOHVBHF NVTU CF JNQPTTJCMF 5IFSF BSF MBOHVBHFT UIBU IBWF QVSQPTFMZ NBEF JU
JOIVNBOMZ EJƸDVMU UP XSJUF TVDI QSPHSBNT CVU )BTLFMM JT OPU POF PG UIFN
$0/5&/54 YYYJW

" GFX XPSET UP OFX QSPHSBNNFST


8FƊWF USJFE WFSZ IBSE UP NBLF UIJT CPPL BT BDDFTTJCMF BT QPTTJ
CMF OP NBUUFS ZPVS MFWFM PG QSFWJPVT FYQFSJFODF 8F IBWF LFQU
DPNQBSJTPOT BOE NFOUJPOT PG PUIFS MBOHVBHFT UP B NJOJNVN
BOE XF QSPNJTF UIBU JG XF DPNQBSF TPNFUIJOH JO )BTLFMM UP
TPNFUIJOH JO BOPUIFS MBOHVBHF UIBU DPNQBSJTPO JT OPU JUTFMG
DSVDJBM UP VOEFSTUBOEJOH UIF )BTLFMM ƈ JUƊT KVTU B MJUUMF FYUSB GPS
UIPTF XIP EP LOPX UIF PUIFS MBOHVBHF
)PXFWFS FTQFDJBMMZ BT UIF CPPL QSPHSFTTFT BOE UIF FYFSDJTFT
BOE QSPKFDUT HFU NPSF ƌSFBM ƍ UIFSF BSF HPJOH UP CF UFSNT BOE
DPODFQUT UIBU XF EP OPU IBWF UIF TQBDF UP FYQMBJO GVMMZ CVU
UIBU BSF SFMBUJWFMZ XFMM LOPXO BNPOH QSPHSBNNFST :PV NBZ
IBWF UP EP JOUFSOFU TFBSDIFT GPS UFSNT MJLF +40/ 5IF OFYU
TFDUJPO PG UIJT JOUSPEVDUJPO SFGFSFODFT UIJOHT UIBU ZPV NBZ OPU
LOPX BCPVU CVU QSPHSBNNFST XJMM ƈ EPOƊU QBOJD 8F UIJOL
ZPVƊMM TUJMM HFU TPNFUIJOH PVU PG SFBEJOH JU CVU JG OPU JUƊT OPU
TPNFUIJOH UP XPSSZ BCPVU 5IF GBDU UIBU ZPV EPOƊU LOPX FWFSZ
UFSN JO UIJT CPPL CFGPSF ZPV DPNF UP JU JT OPU B TJHO UIBU ZPV
DBOƊU MFBSO )BTLFMM PS BSFOƊU SFBEZ GPS UIJT JUƊT POMZ B TJHO UIBU
ZPV EPOƊU LOPX FWFSZUIJOH ZFU BOE TJODF OP POF EPFT ZPVƊSF JO
ƶOF DPNQBOZ
"MPOH UIPTF TBNF MJOFT UIJT CPPL EPFT OPU PƵFS NVDI JO
TUSVDUJPO PO VTJOH UIF UFSNJOBM BOE UFYU FEJUPS 5IF JOTUSVD
UJPOT QSPWJEFE BTTVNF ZPV LOPX IPX UP ƶOE ZPVS XBZ BSPVOE
ZPVS UFSNJOBM BOE VOEFSTUBOE IPX UP EP TJNQMF UBTLT MJLF
$0/5&/54 YYYW

NBLF B EJSFDUPSZ PS PQFO B ƶMF %VF UP UIF OVNCFS PG UFYU


FEJUPST BWBJMBCMF XF EP OPU QSPWJEF TQFDJƶD JOTUSVDUJPOT GPS
BOZ PG UIFN
*G ZPV OFFE IFMQ PS XPVME MJLF UP TUBSU HFUUJOH UP LOPX UIF
DPNNVOJUJFT PG GVODUJPOBM QSPHSBNNFST UIFSF BSF TFWFSBM
PQUJPOT 5IF 'SFFOPEF *3$ DIBOOFM #haskell-beginners IBT
UFBDIFST XIP XJMM CF HMBE UP IFMQ ZPV BOE UIFZ FTQFDJBMMZ
XFMDPNF RVFTUJPOT SFHBSEJOH TQFDJƶD QSPCMFNT UIBU ZPV BSF
USZJOH UP TPMWF 5IFSF BSF BMTP 4MBDL DIBOOFMT BOE TVCSFEEJUT
XIFSF )BTLFMMFST DPOHSFHBUF BMPOH XJUI B QMFUIPSB PG )BTLFMM
PSJFOUFE CMPHT NBOZ PG XIJDI BSF NFOUJPOFE JO GPPUOPUFT
BOE SFDPNNFOEFE SFBEJOHT UISPVHIPVU UIF CPPL .BOZ PG
PVS SFBEFST BMTP QSPHSBN JO MBOHVBHFT MJLF 4XJǒ BOE 4DBMB TP
ZPV NBZ XBOU UP JOWFTUJHBUF UIPTF DPNNVOJUJFT BT XFMM

)BTLFWBOHFMJTN
5IF SFTU PG UIJT JOUSPEVDUJPO XJMM HJWF TPNF CBDLHSPVOE PG
)BTLFMM BOE XJMM NBLF SFGFSFODF UP PUIFS QSPHSBNNJOH MBO

*G ZPVƊSF RVJUF OFX BOE VOTVSF XIBU UP EP BCPVU UFYU FEJUPST ZPV NJHIU DPOTJEFS
"UPN *UƊT GSFF PQFOTPVSDF BOE DPOƶHVSBCMF 4VCMJNF 5FYU IBT TFSWFE +VMJF XFMM UISPVHI
PVU UIF XSJUJOH PG UIF CPPL CVU JT OPU GSFF $ISJT VTFT &NBDT NPTU PG UIF UJNF &NBDT
JT WFSZ QPQVMBS BNPOH QSPHSBNNFST CVU IBT JUT PXO MFBSOJOH DVSWF 7JN JT BOPUIFS
QPQVMBS UFYU FEJUPS XJUI JUT PXO MFBSOJOH DVSWF *G ZPV IBWF OP FYQFSJFODF XJUI &NBDT PS
7JN XFƊE SFBMMZ SFDPNNFOE TUJDLJOH XJUI TPNFUIJOH MJLF 4VCMJNF PS "UPN GPS OPX

'SFFOPEF *3$ *OUFSOFU 3FMBZ $IBU
JT B OFUXPSL PG DIBOOFMT GPS UFYUVBM DIBU 5IFSF
BSF PUIFS *3$ OFUXPSLT BSPVOE BT XFMM BT PUIFS HSPVQ DIBU QMBUGPSNT CVU UIF 'SFFOPEF
*3$ DIBOOFMT GPS )BTLFMM BSF QPQVMBS NFFUJOH QMBDFT GPS UIF )BTLFMM DPNNVOJUZ 5IFSF
BSF TFWFSBM XBZT UP BDDFTT 'SFFOPEF *3$ JODMVEJOH *STTJ BOE )FY$IBU JG ZPVƊSF JOUFSFTUFE
JO HFUUJOH UP LOPX UIF DPNNVOJUZ JO UIFJS OBUVSBM IBCJUBU
$0/5&/54 YYYWJ

HVBHFT BOE TUZMFT *G ZPVƊSF B OFX QSPHSBNNFS JU JT QPTTJCMF


OPU BMM PG UIJT XJMM NBLF TFOTF BOE UIBUƊT PLBZ 5IF SFTU PG UIF
CPPL JT XSJUUFO XJUI CFHJOOFST JO NJOE BOE UIF GFBUVSFT XFƊSF
PVUMJOJOH XJMM NBLF NPSF TFOTF BT ZPV XPSL UISPVHI UIF CPPL
8FƊSF HPJOH UP DPNQBSF )BTLFMM B CJU XJUI PUIFS MBOHVBHFT
UP EFNPOTUSBUF XIZ XF UIJOL VTJOH )BTLFMM JT WBMVBCMF )BTLFMM
JT B MBOHVBHF JO B QSPHSFTTJPO PG MBOHVBHFT EBUJOH CBDL UP 
XIFO .- XBT JOWFOUFE CZ 3PCJO .JMOFS BOE PUIFST BU UIF
6OJWFSTJUZ PG &EJOCVSHI .- XBT JUTFMG JOƷVFODFE CZ *48*.
XIJDI XBT JO UVSO JOƷVFODFE CZ "-(0-  BOE -JTQ 8F
NFOUJPO UIJT MJOFBHF CFDBVTF )BTLFMM JTOƊU OFX 5IF NPTU QPQ
VMBS JNQMFNFOUBUJPO PG )BTLFMM UIF (MBTHPX )BTLFMM $PNQJMFS
()$
JT NBUVSF BOE XFMMNBEF )BTLFMM CSJOHT UPHFUIFS TPNF
OJDF EFTJHO DIPJDFT UIBU NBLF GPS B MBOHVBHF UIBU PƵFST NPSF
FYQSFTTJWFOFTT UIBO 3VCZ CVU NPSF UZQF TBGFUZ UIBO BOZ MBO
HVBHF QSFTFOUMZ JO XJEF VTF DPNNFSDJBMMZ
*O  UIF "-(0- EJBMFDU IBE UIF GPMMPXJOH GFBUVSFT
CVJMU JOUP UIF MBOHVBHF

 6TFSEFƶOFE SFDPSE UZQFT

 6TFSEFƶOFE TVN UZQFT VOJPOT OPU MJNJUFE UP TJNQMF


FOVNFSBUJPOT


 4XJUDIDBTF FYQSFTTJPOT TVQQPSUJOH UIF TVN UZQFT

 $PNQJMFUJNF FOGPSDFE DPOTUBOU WBMVFT EFDMBSFE XJUI =


SBUIFS UIBO :=
$0/5&/54 YYYWJJ

 6OJƶFE TZOUBY GPS VTJOH WBMVF BOE SFGFSFODF UZQFT ƈ OP


NBOVBM QPJOUFS EFSFGFSFODJOH

 $MPTVSFT XJUI MFYJDBM TDPQJOH XJUIPVU UIJT NBOZ GVOD


UJPOBM QBUUFSOT GBMM BQBSU


 *NQMFNFOUBUJPOBHOPTUJD QBSBMMFMJ[FE FYFDVUJPO PG QSP


DFEVSFT

 .VMUJQBTT DPNQJMBUJPO ƈ ZPV DBO EFDMBSF TUVƵ BǒFS ZPV


VTF JU

"T PG UIF FBSMZ TU DFOUVSZ NBOZ QPQVMBS MBOHVBHFT VTFE


DPNNFSDJBMMZ EPOƊU IBWF BOZUIJOH FRVJWBMFOU UP PS CFUUFS UIBO
XIBU "-(0- IBE 8F NFOUJPO UIJT CFDBVTF XF CFMJFWF
UFDIOPMPHJDBM QSPHSFTT JO DPNQVUFS TDJFODF QSPHSBNNJOH
BOE QSPHSBNNJOH MBOHVBHFT JT QPTTJCMF EFTJSBCMF BOE DSJUJDBM
UP TPǒXBSF CFDPNJOH B USVF FOHJOFFSJOH EJTDJQMJOF #Z UIBU
XF NFBO UIBU XIJMF UIF QISBTF ƌTPǒXBSF FOHJOFFSJOHƍ JT JO
DPNNPO VTF FOHJOFFSJOH EJTDJQMJOFT JOWPMWF UIF BQQMJDBUJPO
PG CPUI TDJFOUJƶD BOE QSBDUJDBM LOPXMFEHF UP UIF DSFBUJPO BOE
NBJOUFOBODF PG CFUUFS TZTUFNT "T UIF BWBJMBCMF NBUFSJBMT
DIBOHF BOE BT LOPXMFEHF HSPXT TP NVTU FOHJOFFST
)BTLFMM MFWFSBHFT NPSF PG UIF EFWFMPQNFOUT JO QSPHSBN
NJOH MBOHVBHFT JOWFOUFE TJODF "-(0- UIBO NPTU MBOHVBHFT
JO QPQVMBS VTF CVU XJUI UIF BEEFE CFOFƶU PG B NBUVSF JNQMF
NFOUBUJPO BOE TPVOE EFTJHO 4PNFUJNFT XF IFBS )BTLFMM CF
JOH EJTNJTTFE BT ƌBDBEFNJDƍ CFDBVTF JU JT SFMBUJWFMZ VQUPEBUF
$0/5&/54 YYYWJJJ

XJUI UIF DVSSFOU TUBUF PG NBUIFNBUJDT BOE DPNQVUFS TDJFODF


SFTFBSDI *O PVS WJFX UIBU QSPHSFTT JT HPPE BOE IFMQT VT TPMWF
QSBDUJDBM QSPCMFNT JO NPEFSO DPNQVUJOH BOE TPǒXBSF EFTJHO
1SPHSFTT JT QPTTJCMF BOE EFTJSBCMF CVU JU JT OPU NPOPUPOJD PS
JOFWJUBCMF 5IF IJTUPSZ PG UIF XPSME JT SJEEMFE XJUI FYBNQMFT
PG VOFWFO QSPHSFTT 'PS FYBNQMF JU JT FTUJNBUFE UIBU TDVSWZ
LJMMFE UXP NJMMJPO TBJMPST CFUXFFO UIF ZFBST  BOE 
8FTUFSO DVMUVSF IBT GPSHPUUFO UIF DVSF GPS TDVSWZ NVMUJQMF
UJNFT "T FBSMZ BT  UIF 4VSHFPO (FOFSBM PG UIF &BTU *O
EJB $PNQBOZ SFDPNNFOEFE CSJOHJOH DJUSVT PO WPZBHFT GPS
TDVSWZ *U TBWFE MJWFT CVU UIF VOEFSTUBOEJOH PG XIZ DJUSVT
DVSFE TDVSWZ XBT JODPSSFDU 5IJT MFE UP UIF VTF PG MJNFT XIJDI
IBWF B MPXFS WJUBNJO $ DPOUFOU UIBO MFNPOT BOE TDVSWZ SF
UVSOFE VOUJM BTDPSCJD BDJE XBT EJTDPWFSFE JO  *OEJTDJQMJOF
BOE TUVCCPSOOFTT UIF #SJUJTI /BWZ TUVDL XJUI MJNFT EFTQJUF
TBJMPST DPOUJOVJOH UP EJF GSPN TDVSWZ
DBO IPME CBDL QSPHSFTT
8FƊE SBUIFS IBWF B EPDUPS XIP JT XJMMJOH UP VOEFSTUBOE UIBU
IF NBLFT NJTUBLFT XJMM CF SFTQPOTJWF UP OFX JOGPSNBUJPO
BOE FWFO BDUJWFMZ TFFL UP FYQBOE IJT VOEFSTUBOEJOH SBUIFS
UIBO POF UIBU IVOLFST EPXO XJUI B QFU UIFPSZ JOGPSNFE CZ
BOFDEPUF
5IFSF BSF PUIFS XBZT UP QSFWFOU TDVSWZ KVTU BT UIFSF BSF
PUIFS QSPHSBNNJOH MBOHVBHFT ZPV DBO VTF UP XSJUF TPǒXBSF
0S QFSIBQT ZPV BSF BO FYQMPSFS XIP EPFTOƊU CFMJFWF TDVSWZ
DBO IBQQFO UP ZPV #VU QBDLJOH MFNPOT QSPWJEFT TPNF JO
TVSBODF PO UIPTF MPOH WPZBHFT 4JNJMBSMZ IBWJOH )BTLFMM JO
$0/5&/54 YYYJY

ZPVS UPPMLJU FWFO XIFO JUƊT OPU ZPVS POMZ UPPM QSPWJEFT UZQF
TBGFUZ BOE QSFEJDUBCJMJUZ UIBU DBO JNQSPWF ZPVS TPǒXBSF EFWFM
PQNFOU #VHHZ TPǒXBSF NJHIU OPU MJUFSBMMZ NBLF ZPVS UFFUI
GBMM PVU CVU TPǒXBSF QSPCMFNT BSF GBS GSPN USJWJBM BOE XIFO
UIFSF BSF CFUUFS XBZT UP TPMWF UIPTF QSPCMFNT ƈ OPU QFSGFDU
CVU CFUUFS ƈ JUƊT XPSUI ZPVS UJNF UP JOWFTUJHBUF UIFN
4FU ZPVS MJNFT BTJEF GPS OPX BOE KPJO VT BU UIF MFNPOBEF
TUBOE

8IBUƊT JO UIJT CPPL


5IJT CPPL JT NPSF PG B DPVSTF UIBO B CPPL TPNFUIJOH UP
CF XPSLFE UISPVHI 5IFSF BSF FYFSDJTFT TQSJOLMFE MJCFSBMMZ
UISPVHIPVU UIF CPPL XF FODPVSBHF ZPV UP EP UIFN FWFO
XIFO UIFZ TFFN TJNQMF 5IPTF FYFSDJTFT BSF XIFSF UIF NBKPS
JUZ PG ZPVS FQJQIBOJFT XJMM DPNF GSPN /P BNPVOU PG DIBUUFS
JOH OP NBUUFS IPX XFMM TUSVDUVSFE BOE TVJUFE UP ZPVS UFNQFS
BNFOU XJMM CF BT FƵFDUJWF BT EPJOH UIF XPSL *G ZPV EP HFU UP
B MBUFS DIBQUFS BOE ƶOE ZPV EJE OPU VOEFSTUBOE B DPODFQU PS
TUSVDUVSF XFMM FOPVHI ZPV NBZ XBOU UP SFUVSO UP BO FBSMJFS
DIBQUFS BOE EP NPSF FYFSDJTFT VOUJM ZPV VOEFSTUBOE JU
8F CFMJFWF UIBU TQBDFE SFQFUJUJPO BOE JUFSBUJWF EFFQFOJOH
BSF FƵFDUJWF TUSBUFHJFT GPS MFBSOJOH BOE UIF TUSVDUVSF PG UIF
CPPL SFƷFDUT UIJT :PV NBZ OPUJDF XF NFOUJPO TPNFUIJOH
POMZ CSJFƷZ BU ƶSTU UIFO SFUVSO UP JU PWFS BOE PWFS "T ZPVS
FYQFSJFODF XJUI )BTLFMM EFFQFOT ZPV IBWF B CBTF GSPN XIJDI
$0/5&/54 YM

UP NPWF UP B EFFQFS MFWFM PG VOEFSTUBOEJOH 5SZ OPU UP XPSSZ


UIBU ZPV EPOƊU VOEFSTUBOE TPNFUIJOH DPNQMFUFMZ UIF ƶSTU UJNF
XF NFOUJPO JU #Z NPWJOH UISPVHI UIF FYFSDJTFT BOE SFUVSOJOH
UP DPODFQUT ZPV DBO EFWFMPQ B TPMJE JOUVJUJPO GPS GVODUJPOBM
QSPHSBNNJOH
5IF FYFSDJTFT JO UIF ƶSTU GFX DIBQUFST BSF EFTJHOFE UP SBQJEMZ
GBNJMJBSJ[F ZPV XJUI CBTJD )BTLFMM TZOUBY BOE UZQF TJHOBUVSFT
CVU ZPV TIPVME FYQFDU FYFSDJTFT UP HSPX NPSF DIBMMFOHJOH
JO FBDI TVDDFTTJWF DIBQUFS 8IFSF QPTTJCMF SFBTPO UISPVHI
UIF DPEF TBNQMFT BOE FYFSDJTFT JO ZPVS IFBE ƶSTU UIFO UZQF
UIFN PVU ƈ FJUIFS JOUP UIF 3&1- PS JOUP B TPVSDF ƶMF ƈ BOE
DIFDL UP TFF JG ZPV XFSF SJHIU 5IJT XJMM NBYJNJ[F ZPVS BCJMJUZ
UP VOEFSTUBOE BOE SFBTPO BCPVU QSPHSBNT BOE BCPVU )BTLFMM
-BUFS FYFSDJTFT NBZ CF EJƸDVMU *G ZPV HFU TUVDL PO BO FYFSDJTF
GPS BO FYUFOEFE QFSJPE PG UJNF QSPDFFE BOE SFUVSO UP JU BU B
MBUFS EBUF
8F DPWFS B NJY PG QSBDUJDBM BOE BCTUSBDU NBUUFST SFRVJSFE
UP VTF )BTLFMM GPS B XJEF WBSJFUZ PG QSPKFDUT $ISJTƊT FYQFSJFODF
JT QSJODJQBMMZ XJUI QSPEVDUJPO CBDLFOE TZTUFNT BOE GSPOUFOE
XFC BQQMJDBUJPOT +VMJF JT B MJOHVJTU BOE UFBDIFS CZ USBJOJOH
BOE FEVDBUJPO BOE MFBSOJOH )BTLFMM XBT IFS ƶSTU FYQFSJFODF
XJUI DPNQVUFS QSPHSBNNJOH 5IF FEVDBUJPOBM QSJPSJUJFT PG
UIJT CPPL BSF CJBTFE CZ UIPTF FYQFSJFODFT 0VS HPBM JT UP IFMQ

5IJT JT TIPSU GPS SFBEFWBMQSJOU MPPQ BO JOUFSBDUJWF QSPHSBNNJOH TIFMM UIBU FWBMVBUFT
FYQSFTTJPOT BOE SFUVSOT SFTVMUT JO UIF TBNF FOWJSPONFOU 5IF 3&1- XFƊMM CF VTJOH JT
DBMMFE ()$J ƈ ƉJƊ GPS ƌJOUFSBDUJWFƍ
$0/5&/54 YMJ

ZPV OPU KVTU XSJUF UZQFTBGF GVODUJPOBM DPEF CVU UP VOEFSTUBOE


JU PO B EFFQ FOPVHI MFWFM UIBU ZPV DBO HP GSPN IFSF UP NPSF
BEWBODFE )BTLFMM QSPKFDUT JO B WBSJFUZ PG XBZT EFQFOEJOH PO
ZPVS PXO JOUFSFTUT BOE QSJPSJUJFT
&BDI DIBQUFS GPDVTFT PO EJƵFSFOU BTQFDUT PG B QBSUJDVMBS
UPQJD 8F TUBSU XJUI B TIPSU JOUSPEVDUJPO UP UIF MBNCEB DBMDV
MVT 8IBU EPFT UIJT IBWF UP EP XJUI QSPHSBNNJOH "MM NPEFSO
GVODUJPOBM MBOHVBHFT BSF CBTFE PO UIF MBNCEB DBMDVMVT BOE B
QBTTJOH GBNJMJBSJUZ XJUI JU XJMM IFMQ ZPV EPXO UIF SPBE XJUI
)BTLFMM *G ZPVƊWF VOEFSTUPPE UIF MBNCEB DBMDVMVT VOEFS
TUBOEJOH UIF GFBUVSF LOPXO BT DVSSZJOH XJMM CF B CSFF[F GPS
FYBNQMF
5IF OFYU GFX DIBQUFST DPWFS CBTJD FYQSFTTJPOT BOE GVODUJPOT
JO )BTLFMM TPNF TJNQMF PQFSBUJPOT XJUI TUSJOHT UFYU
BOE B GFX
FTTFOUJBM UZQFT :PV NBZ GFFM B TUSPOH UFNQUBUJPO FTQFDJBMMZ JG
ZPV IBWF QSPHSBNNFE QSFWJPVTMZ UP TLJN PS TLJQ UIPTF ƶSTU
DIBQUFST 1MFBTF EP OPU EP UIJT &WFO JG UIPTF ƶSTU DIBQUFST BSF
DPWFSJOH DPODFQUT ZPVƊSF GBNJMJBS XJUI JUƊT JNQPSUBOU UP TQFOE
UJNF HFUUJOH DPNGPSUBCMF XJUI )BTLFMMƊT UFSTF TZOUBY NBLJOH
TVSF ZPV VOEFSTUBOE UIF EJƵFSFODF CFUXFFO XPSLJOH JO UIF
3&1- BOE XPSLJOH JO TPVSDF ƶMFT BOE CFDPNJOH GBNJMJBS XJUI
UIF DPNQJMFSƊT TPNFUJNFT RVJSLZ FSSPS NFTTBHFT $FSUBJOMZ
ZPV NBZ XPSL RVJDLMZ UISPVHI UIPTF DIBQUFST ƈ KVTU EPOƊU
TLJQ UIFN
'SPN UIFSF XF CVJME CPUI PVUXBSE BOE VQXBSE TP UIBU ZPVS
VOEFSTUBOEJOH PG )BTLFMM CPUI CSPBEFOT BOE EFFQFOT 8IFO
$0/5&/54 YMJJ

ZPV ƶOJTI UIJT CPPL ZPV XJMM OPU KVTU LOPX XIBU NPOBET
BSF ZPV XJMM LOPX IPX UP VTF UIFN FƵFDUJWFMZ JO ZPVS PXO
QSPHSBNT BOE VOEFSTUBOE UIF VOEFSMZJOH BMHFCSB JOWPMWFE
8F QSPNJTF ƈ ZPV XJMM 8F POMZ BTL UIBU ZPV EP OPU HP PO UP
XSJUF B NPOBE UVUPSJBM PO ZPVS CMPH UIBU FYQMBJOT IPX NPOBET
BSF SFBMMZ KVTU MJLF KBMBQFOP QPQQFST
*O FBDI DIBQUFS ZPV DBO FYQFDU

Ƒ BEEJUJPOT UP ZPVS WPDBCVMBSZ PG TUBOEBSE GVODUJPOT

Ƒ TZOUBDUJD QBUUFSOT UIBU CVJME PO FBDI PUIFS

Ƒ UIFPSFUJDBM GPVOEBUJPOT TP ZPV VOEFSTUBOE IPX )BTLFMM


XPSLT

Ƒ JMMVTUSBUJWF FYBNQMFT PG IPX UP SFBE )BTLFMM DPEF

Ƒ TUFQCZTUFQ EFNPOTUSBUJPOT PG IPX UP XSJUF ZPVS PXO


GVODUJPOT

Ƒ FYQMBOBUJPOT PG IPX UP SFBE DPNNPO FSSPS NFTTBHFT BOE


IPX UP BWPJE UIPTF FSSPST

Ƒ FYFSDJTFT PG WBSZJOH EJƸDVMUZ TQSJOLMFE UISPVHIPVU

Ƒ EFƶOJUJPOT PG JNQPSUBOU UFSNT

8F IBWF QVU EFƶOJUJPOT BU UIF FOE PG NPTU DIBQUFST &BDI


UFSN JT PG DPVSTF EFƶOFE XJUIJO UIF CPEZ PG UIF DIBQUFS CVU
$0/5&/54 YMJJJ

XF BEEFE TFQBSBUF EFƶOJUJPOT BU UIF FOE BT B QPJOU PG SFWJFX


*G ZPVƊWF UBLFO TPNF UJNF PƵ CFUXFFO POF DIBQUFS BOE UIF
OFYU UIF EFƶOJUJPOT DBO SFNJOE ZPV PG XIBU ZPV IBWF BMSFBEZ
MFBSOFE BOE PG DPVSTF UIFZ NBZ CF SFGFSSFE UP BOZ UJNF ZPV
OFFE B SFGSFTIFS
5IFSF BSF BMTP SFDPNNFOEBUJPOT BU UIF FOE PG NPTU DIBQ
UFST GPS GPMMPXVQ SFBEJOH 5IFZ BSF DFSUBJOMZ OPU SFRVJSFE CVU
BSF SFTPVSDFT XF QFSTPOBMMZ GPVOE BDDFTTJCMF BOE IFMQGVM UIBU
NBZ IFMQ ZPV MFBSO NPSF BCPVU UPQJDT DPWFSFE JO UIF DIBQUFS

#FTU QSBDUJDFT GPS FYBNQMFT BOE FYFSDJTFT


8F IBWF USJFE UP JODMVEF B WBSJFUZ PG FYBNQMFT BOE FYFSDJTFT JO
FBDI DIBQUFS 8IJMF XF IBWF NBEF FWFSZ FƵPSU UP JODMVEF POMZ
FYFSDJTFT UIBU TFSWF B DMFBS QFEBHPHJDBM QVSQPTF XF SFDPHOJ[F
UIBU OPU BMM JOEJWJEVBMT FOKPZ PS MFBSO BT NVDI GSPN FWFSZ
UZQF PG EFNPOTUSBUJPO PS FYFSDJTF "MTP TJODF PVS SFBEFST
XJMM OFDFTTBSJMZ DPNF UP UIF CPPL XJUI EJƵFSFOU CBDLHSPVOET
TPNF FYFSDJTFT NBZ TFFN UPP FBTZ PS EJƸDVMU UP ZPV CVU CF
KVTU SJHIU GPS TPNFPOF FMTF %P ZPVS CFTU UP XPSL UISPVHI
BT NBOZ FYFSDJTFT BT TFFNT QSBDUJDBM GPS ZPV #VU JG ZPV TLJQ
BMM UIF UZQFT BOE UZQFDMBTTFT FYFSDJTFT BOE UIFO ƶOE ZPVSTFMG
DPOGVTFE XIFO XF HFU UP .POPJE CZ BMM NFBOT DPNF CBDL
BOE EP NPSF FYFSDJTFT VOUJM ZPV VOEFSTUBOE
)FSF BSF B GFX UIJOHT UP LFFQ JO NJOE UP HFU UIF NPTU PVU
PG UIFN
$0/5&/54 YMJW

Ƒ &YBNQMFT BSF VTVBMMZ EFTJHOFE UP EFNPOTUSBUF XJUI SFBM


DPEF XIBU XFƊWF KVTU UBMLFE PS BSF BCPVU UP UBML BCPVU JO
GVSUIFS EFUBJM

Ƒ :PV BSF JOUFOEFE UP UZQF BMM PG UIF FYBNQMFT JOUP UIF 3&1-
PS B ƶMF BOE MPBE UIFN 8F TUSPOHMZ FODPVSBHF ZPV UP
BUUFNQU UP NPEJGZ UIF FYBNQMF BOE QMBZ XJUI UIF DPEF BG
UFS ZPVƊWF NBEF JU XPSL 'PSNJOH IZQPUIFTFT BCPVU XIBU
FƵFDU DIBOHFT XJMM IBWF BOE WFSJGZJOH UIFN JT DSJUJDBM *U
JT CFUUFS UP UZQF UIF DPEF FYBNQMFT BOE FYFSDJTFT ZPVSTFMG
SBUIFS UIBO DPQZ BOE QBTUF CFDBVTF UZQJOH NBLFT ZPV QBZ
NPSF BUUFOUJPO UP JU

Ƒ 4PNFUJNFT UIF FYBNQMFT BSF EFTJHOFE JOUFOUJPOBMMZ UP CF


CSPLFO $IFDL TVSSPVOEJOH QSPTF JG ZPVƊSF DPOGVTFE CZ
BO VOFYQFDUFE FSSPS BT XF XJMM OPU TIPX ZPV DPEF UIBU
EPFTOƊU XPSL XJUIPVU DPNNFOUJOH PO UIF CSFBLBHF *G JUƊT
TUJMM CSPLFO BOE JUƊT OPU TVQQPTFE UP CF ZPV TIPVME TUBSU
DIFDLJOH ZPVS TZOUBY BOE GPSNBUUJOH GPS FSSPST

Ƒ /PU FWFSZ FYBNQMF JT EFTJHOFE UP CF FOUFSFE JOUP UIF


3&1- OPU FWFSZ FYBNQMF JT EFTJHOFE UP CF FOUFSFE JOUP
B ƶMF 0ODF XF IBWF FYQMBJOFE UIF TZOUBDUJD EJƵFSFODFT
CFUXFFO ƶMFT BOE 3&1- FYQSFTTJPOT ZPV BSF FYQFDUFE UP
QFSGPSN UIF USBOTMBUJPO CFUXFFO UIF UXP ZPVSTFMG :PV
TIPVME CF BDDVTUPNFE UP XPSLJOH XJUI DPEF JO BO JOUFSBD
UJWF NBOOFS CZ UIF UJNF ZPV ƶOJTI UIF CPPL :PVƊMM XBOU
$0/5&/54 YMW

UP HSBEVBMMZ NPWF BXBZ GSPN UZQJOH DPEF FYBNQMFT BOE


FYFSDJTFT FYDFQU JO MJNJUFE DBTFT EJSFDUMZ JOUP ()$J BOE
EFWFMPQ UIF IBCJU PG XPSLJOH JO TPVSDF ƶMFT &EJUJOH BOE
NPEJGZJOH DPEF BT ZPV XJMM CF EPJOH B MPU BT ZPV SFXPSL
FYFSDJTFT JT FBTJFS BOE NPSF QSBDUJDBM JO B TPVSDF ƶMF :PV
XJMM TUJMM MPBE ZPVS DPEF JOUP ()$J UP SVO JU

Ƒ :PV NBZ XBOU UP LFFQ FYFSDJTFT FTQFDJBMMZ MPOHFS POFT BT


OBNFE NPEVMFT 5IFSF BSF TFWFSBM FYFSDJTFT FTQFDJBMMZ
MBUFS JO UIF CPPL UIBU XF SFUVSO UP TFWFSBM UJNFT BOE CFJOH
BCMF UP SFMPBE UIF XPSL ZPVƊWF BMSFBEZ EPOF BOE BEE POMZ
UIF OFX QBSUT XJMM TBWF ZPV B MPU PG UJNF BOE HSJFG 8F
IBWF USJFE UP OPUF TPNF PG UIF FYFSDJTFT XIFSF UIJT XJMM
CF FTQFDJBMMZ IFMQGVM

Ƒ &YFSDJTFT BU UIF FOE PG UIF DIBQUFS NBZ JODMVEF TPNF SF


WJFX RVFTUJPOT DPWFSJOH NBUFSJBM GSPN QSFWJPVT DIBQUFST
BOE BSF NPSF PS MFTT PSEFSFE GSPN MFBTU UP NPTU DIBMMFOH
JOH :PVS NJMFBHF NBZ WBSZ

Ƒ &WFO FYFSDJTFT UIBU TFFN FBTZ DBO JODSFBTF ZPVS ƷVFODZ


JO B UPQJD 8F EP OPU GFUJTIJ[F EJƸDVMUZ GPS EJƸDVMUZƊT
TBLF 8F KVTU XBOU ZPV UP VOEFSTUBOE UIF UPQJDT BT XFMM
BT QPTTJCMF 5IBU DBO NFBO DPNJOH BU UIF TBNF QSPCMFN
GSPN EJƵFSFOU BOHMFT

Ƒ 8F BTL ZPV UP XSJUF BOE UIFO SFXSJUF VTJOH EJƵFSFOU


TZOUBY
B MPU PG GVODUJPOT 'FX QSPCMFNT IBWF POMZ POF
$0/5&/54 YMWJ

QPTTJCMF TPMVUJPO BOE TPMWJOH UIF TBNF QSPCMFN JO EJG


GFSFOU XBZT JODSFBTFT ZPVS ƷVFODZ BOE DPNGPSU XJUI UIF
XBZ )BTLFMM XPSLT JUT TZOUBY JUT TFNBOUJDT BOE JO TPNF
DBTFT JUT FWBMVBUJPO PSEFS


Ƒ %P OPU GFFM PCMJHBUFE UP EP BMM UIF FYFSDJTFT JO B TJOHMF


TJUUJOH PS FWFO JO B ƶSTU QBTT UISPVHI UIF DIBQUFS *O GBDU
TQBDFE SFQFUJUJPO JT HFOFSBMMZ B NPSF FƵFDUJWF TUSBUFHZ

Ƒ 4PNF FYFSDJTFT QBSUJDVMBSMZ JO UIF FBSMJFS DIBQUFST NBZ


TFFN WFSZ DPOUSJWFE 8FMM UIFZ BSF #VU UIFZ BSF DPO
USJWFE UP QJOQPJOU DFSUBJO MFTTPOT "T UIF CPPL HPFT PO
BOE ZPV IBWF NPSF )BTLFMM VOEFS ZPVS CFMU UIF FYFSDJTFT
CFDPNF MFTT DPOUSJWFE BOE NPSF MJLF ƌSFBM )BTLFMMƍ

Ƒ "OPUIFS CFOFƶU UP XSJUJOH DPEF JO B TPVSDF ƶMF BOE UIFO


MPBEJOH JU JOUP UIF 3&1- JT UIBU ZPV DBO XSJUF DPNNFOUT
BCPVU UIF QSPDFTT ZPV XFOU UISPVHI JO TPMWJOH B QSPCMFN
8SJUJOH PVU ZPVS PXO UIPVHIU QSPDFTT DBO DMBSJGZ ZPVS
UIPVHIUT BOE NBLF UIF TPMWJOH PG TJNJMBS QSPCMFNT FBTJFS
"U UIF WFSZ MFBTU ZPV DBO SFGFS CBDL UP ZPVS DPNNFOUT
BOE MFBSO GSPN ZPVSTFMG

Ƒ 4PNFUJNFT XF JOUFOUJPOBMMZ VOEFSTQFDJGZ GVODUJPO EFG


JOJUJPOT :PVƊMM DPNNPOMZ TFF UIJOHT MJLF

f = undefined
$0/5&/54 YMWJJ

&WFO XIFO ԕ XJMM QSPCBCMZ UBLF OBNFE BSHVNFOUT JO ZPVS


JNQMFNFOUBUJPO XFƊSF OPU HPJOH UP OBNF UIFN GPS ZPV
/PCPEZ XJMM TDBƵPME ZPVS DPEF GPS ZPV JO ZPVS GVUVSF
QSPKFDUT TP EPOƊU FYQFDU UIJT CPPL UP FJUIFS
$IBQUFS 

"MM :PV /FFE JT -BNCEB

&WFO UIF HSFBUFTU


NBUIFNBUJDJBOT UIF POFT
UIBU XF XPVME QVU JOUP
PVS NZUIPMPHZ PG HSFBU
NBUIFNBUJDJBOT IBE UP
EP B HSFBU EFBM PG MFH
XPSL JO PSEFS UP HFU UP
UIF TPMVUJPO JO UIF FOE

%BOJFM 5BNNFUU


$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 "MM :PV /FFE JT -BNCEB


5IJT DIBQUFS QSPWJEFT B WFSZ CSJFG JOUSPEVDUJPO UP UIF MBNCEB
DBMDVMVT B NPEFM PG DPNQVUBUJPO EFWJTFE JO UIF T CZ
"MPO[P $IVSDI " DBMDVMVT JT B NFUIPE PG DBMDVMBUJPO PS SFB
TPOJOH UIF MBNCEB DBMDVMVT JT POF QSPDFTT GPS GPSNBMJ[JOH B
NFUIPE -JLF 5VSJOH NBDIJOFT UIF MBNCEB DBMDVMVT GPSNBM
J[FT UIF DPODFQU PG FƵFDUJWF DPNQVUBCJMJUZ UIVT EFUFSNJOJOH
XIJDI QSPCMFNT PS DMBTTFT PG QSPCMFNT DBO CF TPMWFE
:PV NBZ CF XPOEFSJOH XIFSF UIF )BTLFMM JT :PV NBZ CF
DPOUFNQMBUJOH TLJQQJOH UIJT DIBQUFS :PV NBZ GFFM UFNQUFE
UP TLJQ BIFBE UP UIF GVO TUVƵ XIFO XF CVJME B QSPKFDU
%0/Ɗ5
8FƊSF TUBSUJOH GSPN ƶSTU QSJODJQMFT IFSF TP UIBU XIFO XF
HFU BSPVOE UP CVJMEJOH QSPKFDUT ZPV LOPX XIBU ZPVƊSF EPJOH
:PV EPOƊU TUBSU CVJMEJOH B IPVTF GSPN UIF BUUJD EPXO ZPV TUBSU
GSPN UIF GPVOEBUJPO -BNCEB DBMDVMVT JT ZPVS GPVOEBUJPO
CFDBVTF )BTLFMM JT CVJMU PO JU

 8IBU JT GVODUJPOBM QSPHSBNNJOH


'VODUJPOBM QSPHSBNNJOH JT B DPNQVUFS QSPHSBNNJOH QBSBEJHN
UIBU SFMJFT PO GVODUJPOT NPEFMFE PO NBUIFNBUJDBM GVODUJPOT
5IF FTTFODF PG GVODUJPOBM QSPHSBNNJOH JT UIBU QSPHSBNT BSF
B DPNCJOBUJPO PG FYQSFTTJPOT &YQSFTTJPOT JODMVEF DPODSFUF
WBMVFT WBSJBCMFT BOE BMTP GVODUJPOT 'VODUJPOT IBWF B NPSF
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

TQFDJƶD EFƶOJUJPO UIFZ BSF FYQSFTTJPOT UIBU BSF BQQMJFE UP


BO BSHVNFOU PS JOQVU BOE PODF BQQMJFE DBO CF SFEVDFE PS
FWBMVBUFE *O )BTLFMM BOE JO GVODUJPOBM QSPHSBNNJOH NPSF
HFOFSBMMZ GVODUJPOT BSF ƶSTUDMBTT UIFZ DBO CF VTFE BT WBMVFT
PS QBTTFE BT BSHVNFOUT PS JOQVUT UP ZFU NPSF GVODUJPOT 8FƊMM
EFƶOF UIFTF UFSNT NPSF DBSFGVMMZ BT XF QSPHSFTT UISPVHI UIF
DIBQUFS
'VODUJPOBM QSPHSBNNJOH MBOHVBHFT BSF BMM CBTFE PO UIF
MBNCEB DBMDVMVT 4PNF MBOHVBHFT JO UIJT HFOFSBM DBUFHPSZ
JODPSQPSBUF GFBUVSFT JOUP UIF MBOHVBHF UIBU BSFOƊU USBOTMBUBCMF
JOUP MBNCEB FYQSFTTJPOT )BTLFMM JT B QVSF GVODUJPOBM MBOHVBHF
CFDBVTF JU EPFT OPU 8FƊMM BEESFTT UIJT OPUJPO PG QVSJUZ NPSF
MBUFS JO UIF CPPL CVU JU JTOƊU B KVEHNFOU PG UIF NPSBM XPSUI PG
PUIFS MBOHVBHFT
5IF XPSE QVSJUZ JO GVODUJPOBM QSPHSBNNJOH JT TPNFUJNFT
BMTP VTFE UP NFBO XIBU JT NPSF QSPQFSMZ DBMMFE SFGFSFOUJBM
USBOTQBSFODZ 3FGFSFOUJBM USBOTQBSFODZ NFBOT UIBU UIF TBNF
GVODUJPO HJWFO UIF TBNF WBMVFT UP FWBMVBUF XJMM BMXBZT SFUVSO
UIF TBNF SFTVMU JO QVSF GVODUJPOBM QSPHSBNNJOH BT UIFZ EP
JO NBUI
)BTLFMMƊT QVSF GVODUJPOBM CBTJT BMTP MFOET JU B IJHI EFHSFF
PG BCTUSBDUJPO BOE DPNQPTBCJMJUZ "CTUSBDUJPO BMMPXT ZPV UP
XSJUF TIPSUFS NPSF DPODJTF QSPHSBNT CZ GBDUPSJOH DPNNPO
SFQFBUFE TUSVDUVSFT JOUP NPSF HFOFSJD DPEF UIBU DBO CF SFVTFE
)BTLFMM QSPHSBNT BSF CVJMU GSPN TFQBSBUF JOEFQFOEFOU GVOD
UJPOT LJOE PG MJLF -&(0n  UIF GVODUJPOT BSF CSJDLT UIBU DBO CF
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

BTTFNCMFE BOE SFBTTFNCMFE


5IFTF GFBUVSFT BMTP NBLF )BTLFMMƊT TZOUBY SBUIFS NJOJNBMJTU
BT ZPVƊMM TPPO TFF

 8IBU JT B GVODUJPO


*G XF TUFQ CBDL GSPN VTJOH UIF XPSE ƌMBNCEB ƍ ZPV NPTU MJLFMZ
BMSFBEZ LOPX XIBU B GVODUJPO JT " GVODUJPO JT B SFMBUJPO CF
UXFFO B TFU PG QPTTJCMF JOQVUT BOE B TFU PG QPTTJCMF PVUQVUT 5IF
GVODUJPO JUTFMG EFƶOFT BOE SFQSFTFOUT UIF SFMBUJPOTIJQ 8IFO
ZPV BQQMZ B GVODUJPO TVDI BT BEEJUJPO UP UXP JOQVUT JU NBQT
UIPTF UXP JOQVUT UP BO PVUQVU ƈ UIF TVN PG UIPTF OVNCFST
'PS FYBNQMF MFUƊT JNBHJOF B GVODUJPO OBNFE ԕ UIBU EFƶOFT
UIF GPMMPXJOH SFMBUJPOT XIFSF UIF ƶSTU WBMVF JT UIF JOQVU BOE
UIF TFDPOE JT UIF PVUQVU

ԕ 
 Ӷ
ԕ 
 ӷ
ԕ 
 Ӹ

5IF JOQVU TFU JT \  ^ BOE UIF PVUQVU TFU JT \Ӷ ӷ Ӹ^ "


DSVDJBM QPJOU BCPVU IPX UIFTF SFMBUJPOT BSF EFƶOFE PVS IZQP
UIFUJDBM GVODUJPO XJMM BMXBZT SFUVSO UIF WBMVF Ӷ HJWFO UIF JOQVU
 ƈ OP FYDFQUJPOT

'PS UIPTF XIP XPVME MJLF QSFDJTF UFSNJOPMPHZ UIF JOQVU TFU JT LOPXO BT UIF EPNBJO
" TFU PG VOJRVF WBMVFT UIBU BSF QPTTJCMF PVUQVUT GPS UIF GVODUJPO JT DBMMFE UIF DPEPNBJO
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

*O DPOUSBTU UIF GPMMPXJOH JT OPU B WBMJE GVODUJPO

ԕ 
 ԍ
ԕ 
 Ԏ
ԕ 
 ԏ
5IJT HFUT CBDL UP UIF SFGFSFOUJBM USBOTQBSFODZ XF NFOUJPOFE
FBSMJFS HJWFO UIF TBNF JOQVU UIF PVUQVU TIPVME CF QSFEJDUBCMF
*T UIF GPMMPXJOH GVODUJPO WBMJE

ԕ 
 Ӷ
ԕ 
 Ӷ
ԕ 
 Ӷ
:FT IBWJOH UIF TBNF PVUQVU GPS NPSF UIBO POF JOQVU JT
WBMJE *NBHJOF GPS FYBNQMF UIBU ZPV OFFE B GVODUJPO UIBU
UFTUT B WBMVF GPS CFJOH MFTT UIBO  :PVƊE XBOU JU UP SFUVSO True
XIFO UIF JOQVU XBT MFTT UIBO  BOE False GPS BMM PUIFS DBTFT
*O UIBU DBTF TFWFSBM EJƵFSFOU JOQVUT XJMM SFTVMU JO UIF PVUQVU
True NBOZ NPSF XJMM HJWF B SFTVMU PG False %JƵFSFOU JOQVUT
DBO MFBE UP UIF TBNF PVUQVU
8IBU NBUUFST IFSF JT UIBU UIF SFMBUJPOTIJQ PG JOQVUT BOE
PVUQVUT JT EFƶOFE CZ UIF GVODUJPO BOE UIBU UIF PVUQVU JT QSF
EJDUBCMF XIFO ZPV LOPX UIF JOQVU BOE UIF GVODUJPO EFƶOJUJPO
5IF TFU PG BMM QPTTJCMF PVUQVUT SFMBUFE UP EJƵFSFOU JOQVUT JT UIF SBOHF "MM EPNBJOT BOE
DPEPNBJOT BSF TFUT PG VOJRVF WBMVFT 3BOHFT BSF TFUT PG WBMVFT CVU UIF WBMVFT JO SBOHF
TFUT OFFE OPU CF VOJRVF BOE JO QSBDUJDF WFSZ PǒFO BSF OPU VOJRVF UIBU JT UIF TBNF WBMVF
DBO BQQFBS NVMUJQMF UJNFT JO UIBU TFU &WFSZ WBMVF JO B SBOHF NVTU CF B NFNCFS PG UIF
GVODUJPOƊT DPEPNBJO
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

*O UIF BCPWF FYBNQMFT XF EJEOƊU EFNPOTUSBUF B SFMBUJPOTIJQ


CFUXFFO UIF JOQVUT BOE PVUQVUT -FUƊT MPPL BU BO FYBNQMF UIBU
EPFT EFƶOF UIF SFMBUJPOTIJQ 5IJT GVODUJPO JT BHBJO OBNFE ԕ

ԕ ԧ
 ԧ 
5IJT GVODUJPO UBLFT POF BSHVNFOU XIJDI XF IBWF OBNFE
ԧ 5IF SFMBUJPOTIJQ CFUXFFO UIF JOQVU ԧ BOE UIF PVUQVU JT
EFTDSJCFE JO UIF GVODUJPO CPEZ *U XJMM BEE  UP XIBUFWFS WBMVF
ԧ JT BOE SFUVSO UIBU SFTVMU 8IFO XF BQQMZ UIJT GVODUJPO UP B
WBMVF TVDI BT  XF TVCTUJUVUF UIF WBMVF JO GPS ԧ

ԕ 
  
ԕ BQQMJFE UP  FRVBMT   5IBU UFMMT VT IPX UP NBQ UIF JOQVU
UP BO PVUQVU  BEEFE UP  CFDPNFT 

ԕ 
 
6OEFSTUBOEJOH GVODUJPOT JO UIJT XBZ ƈ BT B NBQQJOH PG B
TFU PG JOQVUT UP B TFU PG PVUQVUT ƈ JT DSVDJBM UP VOEFSTUBOEJOH
GVODUJPOBM QSPHSBNNJOH

 5IF TUSVDUVSF PG MBNCEB UFSNT


5IF MBNCEB DBMDVMVT IBT UISFF CBTJD DPNQPOFOUT PS MBNCEB
UFSNT FYQSFTTJPOT WBSJBCMFT BOE BCTUSBDUJPOT 5IF XPSE FY
QSFTTJPO SFGFST UP B TVQFSTFU PG BMM UIPTF UIJOHT BO FYQSFTTJPO
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

DBO CF B WBSJBCMF OBNF BO BCTUSBDUJPO PS B DPNCJOBUJPO PG


UIPTF UIJOHT 5IF TJNQMFTU FYQSFTTJPO JT B TJOHMF WBSJBCMF 7BSJ
BCMFT IFSF IBWF OP NFBOJOH PS WBMVF UIFZ BSF KVTU OBNFT GPS
QPUFOUJBM JOQVUT UP GVODUJPOT
"O BCTUSBDUJPO JT B GVODUJPO *U JT B MBNCEB UFSN UIBU IBT B
IFBE B MBNCEB
BOE B CPEZ BOE JT BQQMJFE UP BO BSHVNFOU "O
BSHVNFOU JT BO JOQVU WBMVF
"CTUSBDUJPOT DPOTJTU PG UXP QBSUT UIF IFBE BOE UIF CPEZ
5IF IFBE PG UIF GVODUJPO JT B ᅶ MBNCEB
GPMMPXFE CZ B WBSJBCMF
OBNF 5IF CPEZ PG UIF GVODUJPO JT BOPUIFS FYQSFTTJPO 4P B
TJNQMF GVODUJPO NJHIU MPPL MJLF UIJT

ᅶԧԧ
5IF WBSJBCMF OBNFE JO UIF IFBE JT UIF QBSBNFUFS BOE CJOET
BMM JOTUBODFT PG UIBU TBNF WBSJBCMF JO UIF CPEZ PG UIF GVODUJPO
5IBU NFBOT XIFO XF BQQMZ UIJT GVODUJPO UP BO BSHVNFOU
FBDI ԧ JO UIF CPEZ PG UIF GVODUJPO XJMM IBWF UIF WBMVF PG UIBU
BSHVNFOU 8FƊMM EFNPOTUSBUF UIJT JO UIF OFYU TFDUJPO
*O UIF QSFWJPVT TFDUJPO XF XFSF UBMLJOH BCPVU GVODUJPOT
DBMMFE ԕ CVU UIF MBNCEB BCTUSBDUJPO ᅶԧԧ IBT OP OBNF *U JT BO
BOPOZNPVT GVODUJPO " OBNFE GVODUJPO DBO CF DBMMFE CZ OBNF
CZ BOPUIFS GVODUJPO BO BOPOZNPVT GVODUJPO DBOOPU
-FUƊT CSFBL EPXO UIF CBTJD TUSVDUVSF

λ x . x
^─┬─^
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

└────── the extent of the head of the lambda.

λ x . x
^────── the single parameter of the function. This
binds any variables with the same name
in the body of the function.

λ x . x
^── body, the expression the lambda returns
when applied. This is a bound variable.

5IF EPU .
TFQBSBUFT UIF QBSBNFUFST PG UIF MBNCEB GSPN
UIF GVODUJPO CPEZ
5IF BCTUSBDUJPO BT B XIPMF IBT OP OBNF CVU UIF SFBTPO
XF DBMM JU BO BCTUSBDUJPO JT UIBU JU JT B HFOFSBMJ[BUJPO PS BCTUSBD
UJPO GSPN B DPODSFUF JOTUBODF PG B QSPCMFN BOE JU BCTUSBDUT
UISPVHI UIF JOUSPEVDUJPO PG OBNFT 5IF OBNFT TUBOE GPS DPO
DSFUF WBMVFT CVU CZ VTJOH OBNFE WBSJBCMFT XF BMMPX GPS UIF
QPTTJCJMJUZ PG BQQMZJOH UIF HFOFSBM GVODUJPO UP EJƵFSFOU WBMVFT
PS QFSIBQT FWFO WBMVFT PG EJƵFSFOU UZQFT BT XFƊMM TFF MBUFS

8IFO XF BQQMZ UIF BCTUSBDUJPO UP BSHVNFOUT XF SFQMBDF UIF
OBNFT XJUI WBMVFT NBLJOH JU DPODSFUF
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

"MQIB FRVJWBMFODF
0ǒFO XIFO QFPQMF FYQSFTT UIJT GVODUJPO JO MBNCEB DBMDVMVT
ZPVƊMM TFF TPNFUIJOH MJLF

ᅶԧԧ
5IF WBSJBCMF ԧ IFSF JT OPU TFNBOUJDBMMZ NFBOJOHGVM FYDFQU JO
JUT SPMF JO UIBU TJOHMF FYQSFTTJPO #FDBVTF PG UIJT UIFSFƊT B GPSN
PG FRVJWBMFODF CFUXFFO MBNCEB UFSNT DBMMFE BMQIB FRVJWBMFODF
5IJT JT B XBZ PG TBZJOH UIBU

ᅶԧԧ
ᅶԓԓ
ᅶԩԩ

BMM NFBO UIF TBNF UIJOH 5IFZƊSF BMM UIF TBNF GVODUJPO
-FUƊT MPPL OFYU BU XIBU IBQQFOT XIFO XF BQQMZ UIJT BCTUSBD
UJPO UP B WBMVF

 #FUB SFEVDUJPO


8IFO XF BQQMZ B GVODUJPO UP BO BSHVNFOU XF TVCTUJUVUF UIF
JOQVU FYQSFTTJPO GPS BMM JOTUBODFT PG CPVOE WBSJBCMFT XJUIJO
UIF CPEZ PG UIF BCTUSBDUJPO :PV BMTP FMJNJOBUF UIF IFBE PG UIF
BCTUSBDUJPO TJODF JUT POMZ QVSQPTF XBT UP CJOE B WBSJBCMF 5IJT
QSPDFTT JT DBMMFE CFUB SFEVDUJPO
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

-FUƊT VTF UIF GVODUJPO XF IBE BCPWF

ᅶԧԧ
8FƊMM EP PVS ƶSTU CFUB SFEVDUJPO VTJOH B OVNCFS 8F BQQMZ
UIF GVODUJPO BCPWF UP  TVCTUJUVUF  GPS FBDI CPVOE WBSJBCMF
JO UIF CPEZ PG UIF GVODUJPO BOE FMJNJOBUF UIF IFBE

ᅶԧԧ



5IF POMZ CPVOE WBSJBCMF JT UIF TJOHMF ԧ TP BQQMZJOH UIJT


GVODUJPO UP  SFUVSOT  5IJT GVODUJPO JT UIF JEFOUJUZ GVODUJPO
"MM JU EPFT JT BDDFQU B TJOHMF BSHVNFOU ԧ BOE SFUVSO UIBU TBNF
BSHVNFOU 5IF ԧ IBT OP JOIFSFOU NFBOJOH CVU CFDBVTF JU
JT CPVOE JO UIF IFBE PG UIJT GVODUJPO XIFO UIF GVODUJPO JT
BQQMJFE UP BO BSHVNFOU BMM JOTUBODFT PG ԧ XJUIJO UIF GVODUJPO
CPEZ NVTU IBWF UIF TBNF WBMVF
-FUƊT VTF BO FYBNQMF UIBU NJYFT TPNF BSJUINFUJD JOUP PVS
MBNCEB DBMDVMVT 8F VTF UIF QBSFOUIFTFT IFSF UP DMBSJGZ UIBU
UIF CPEZ FYQSFTTJPO JT ԧ  *O PUIFS XPSET XF BSF OPU BQQMZJOH
UIF GVODUJPO UP UIF 

5IF MBNCEB DBMDVMVT DBO EFSJWF OVNCFST GSPN MBNCEB BCTUSBDUJPOT SBUIFS UIBO VTJOH
UIF OVNFSBMT XF BSF GBNJMJBS XJUI CVU UIF BQQMJDBUJPOT DBO CFDPNF RVJUF DVNCFSTPNF
BOE EJƸDVMU UP SFBE

/PUF UIBU UIJT JT UIF TBNF BT UIF JEFOUJUZ GVODUJPO JO NBUIFNBUJDBM OPUBUJPO ց ֓
 ֓
0OF EJƵFSFODF JT UIBU ց ֓
 ֓ JT B EFDMBSBUJPO JOWPMWJOH B GVODUJPO OBNFE ց XIJMF UIF
BCPWF MBNCEB BCTUSBDUJPO JT B GVODUJPO
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

ᅶԧԧ 

8IBU JT UIF SFTVMU JG XF BQQMZ UIJT BCTUSBDUJPO UP  )PX


BCPVU UP 
#FUB SFEVDUJPO JT UIJT QSPDFTT PG BQQMZJOH B MBNCEB UFSN
UP BO BSHVNFOU SFQMBDJOH UIF CPVOE WBSJBCMFT XJUI UIF WBMVF
PG UIF BSHVNFOU BOE FMJNJOBUJOH UIF IFBE &MJNJOBUJOH UIF
IFBE UFMMT ZPV UIF GVODUJPO IBT CFFO BQQMJFE
8F DBO BMTP BQQMZ PVS JEFOUJUZ GVODUJPO UP BOPUIFS MBNCEB
BCTUSBDUJPO

ᅶԧԧ
ᅶԨԨ

*O UIJT DBTF XFƊE TVCTUJUVUF UIF FOUJSF BCTUSBDUJPO JO GPS ԧ


8FƊMM VTF B OFX TZOUBY IFSF <ԧ ੃ ԩ> UP JOEJDBUF UIBU ԩ XJMM CF
TVCTUJUVUFE GPS BMM PDDVSSFODFT PG ԧ IFSF ԩ JT UIF GVODUJPO ᅶԨԨ

8F SFEVDF UIJT BQQMJDBUJPO MJLF UIJT

ᅶԧԧ
ᅶԨԨ

<ԧ ੃ ᅶԨԨ
>
ᅶԨԨ
0VS ƶOBM SFTVMU JT BOPUIFS JEFOUJUZ GVODUJPO 5IFSF JT OP
BSHVNFOU UP BQQMZ JU UP TP XF IBWF OPUIJOH UP SFEVDF
0ODF NPSF CVU UIJT UJNF XFƊMM BEE BOPUIFS BSHVNFOU

ᅶԧԧ
ᅶԨԨ
ԩ
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

"QQMJDBUJPOT JO UIF MBNCEB DBMDVMVT BSF MFǕ BTTPDJBUJWF 5IBU


JT VOMFTT TQFDJƶD QBSFOUIFTFT TVHHFTU PUIFSXJTF UIFZ BTTPDJBUF
PS HSPVQ UP UIF MFǒ 4P UIJT

ᅶԧԧ
ᅶԨԨ
ԩ
DBO CF SFXSJUUFO BT

ᅶԧԧ
ᅶԨԨ

ԩ
0OXBSE XJUI UIF SFEVDUJPO

ᅶԧԧ
ᅶԨԨ

ԩ
<ԧ ੃ ᅶԨԨ
>
ᅶԨԨ
ԩ
<Ԩ ੃ ԩ>
ԩ

8F DBOƊU SFEVDF UIJT BOZ GVSUIFS BT UIFSF JT OPUIJOH MFǒ UP


BQQMZ BOE XF LOPX OPUIJOH BCPVU ԩ
8FƊMM MPPL BU GVODUJPOT CFMPX UIBU IBWF NVMUJQMF IFBET BOE
BMTP GSFF WBSJBCMFT UIBU JT WBSJBCMFT JO UIF CPEZ UIBU BSF OPU
CPVOE CZ UIF IFBE
CVU UIF CBTJD QSPDFTT XJMM SFNBJO UIF TBNF
5IF QSPDFTT PG CFUB SFEVDUJPO TUPQT XIFO UIFSF BSF FJUIFS OP
NPSF IFBET PS MBNCEBT MFǒ UP BQQMZ PS OP NPSF BSHVNFOUT
UP BQQMZ GVODUJPOT UP " DPNQVUBUJPO UIFSFGPSF DPOTJTUT PG BO
JOJUJBM MBNCEB FYQSFTTJPO PS UXP JG ZPV XBOU UP TFQBSBUF UIF
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

GVODUJPO BOE JUT JOQVU


QMVT B ƶOJUF TFRVFODF PG MBNCEB UFSNT
FBDI EFEVDFE GSPN UIF QSFDFEJOH UFSN CZ POF BQQMJDBUJPO PG
CFUB SFEVDUJPO 8F LFFQ GPMMPXJOH UIF SVMFT PG BQQMJDBUJPO
TVCTUJUVUJOH BSHVNFOUT JO GPS CPVOE WBSJBCMFT VOUJM UIFSF BSF
OP NPSF IFBET MFǒ UP FWBMVBUF PS OP NPSF BSHVNFOUT UP BQQMZ
UIFN UP

'SFF WBSJBCMFT
5IF QVSQPTF PG UIF IFBE PG UIF GVODUJPO JT UP UFMM VT XIJDI
WBSJBCMFT UP SFQMBDF XIFO XF BQQMZ PVS GVODUJPO UIBU JT UP
CJOE UIF WBSJBCMFT " CPVOE WBSJBCMF NVTU IBWF UIF TBNF WBMVF
UISPVHIPVU UIF FYQSFTTJPO
#VU TPNFUJNFT UIF CPEZ FYQSFTTJPO IBT WBSJBCMFT UIBU BSF
OPU OBNFE JO UIF IFBE 8F DBMM UIPTF WBSJBCMFT GSFF WBSJBCMFT
*O UIF GPMMPXJOH FYQSFTTJPO

ᅶԧԧԨ
5IF ԧ JO UIF CPEZ JT B CPVOE WBSJBCMF CFDBVTF JU JT OBNFE JO
UIF IFBE PG UIF GVODUJPO XIJMF UIF Ԩ JT B GSFF WBSJBCMF CFDBVTF
JU JT OPU 8IFO XF BQQMZ UIJT GVODUJPO UP BO BSHVNFOU OPUIJOH
DBO CF EPOF XJUI UIF Ԩ *U SFNBJOT JSSFEVDJCMF
5IBU XIPMF BCTUSBDUJPO DBO CF BQQMJFE UP BO BSHVNFOU ԩ
MJLF UIJT ᅶԧԧԨ
ԩ 8FƊMM TIPX BO JOUFSNFEJBUF TUFQ VTJOH UIF
:= TZOUBY XF JOUSPEVDFE BCPWF UIBU NPTU MBNCEB DBMDVMVT
MJUFSBUVSF EPFT OPU TIPX
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 ᅶԧԧԨ
ԩ
8F BQQMZ UIF MBNCEB UP UIF BSHVNFOU ԩ

 ᅶ<ԧ ੃ ԩ>ԧԨ

4JODF ԧ JT UIF CPVOE WBSJBCMF BMM JOTUBODFT PG ԧ JO UIF CPEZ


PG UIF GVODUJPO XJMM CF SFQMBDFE XJUI ԩ 5IF IFBE XJMM CF
FMJNJOBUFE BOE XF SFQMBDF BOZ ԧ JO UIF CPEZ XJUI B ԩ

 ԩԨ
5IF IFBE IBT CFFO BQQMJFE BXBZ BOE UIFSF BSF OP NPSF
IFBET PS CPVOE WBSJBCMFT 4JODF XF LOPX OPUIJOH BCPVU
ԩ PS Ԩ XF DBO SFEVDF UIJT OP GVSUIFS

/PUF UIBU BMQIB FRVJWBMFODF EPFT OPU BQQMZ UP GSFF WBSJ


BCMFT 5IBU JT ᅶԧԧԩ BOE ᅶԧԧԨ BSF OPU FRVJWBMFOU CFDBVTF ԩ
BOE Ԩ NJHIU CF EJƵFSFOU UIJOHT )PXFWFS ᅶԧԨԨԧ BOE ᅶԐԑԑԐ
BSF FRVJWBMFOU EVF UP BMQIB FRVJWBMFODF BT BSF ᅶԧԧԩ BOE ᅶԨԨԩ
CFDBVTF UIF GSFF WBSJBCMF JT MFǒ BMPOF

 .VMUJQMF BSHVNFOUT


&BDI MBNCEB DBO POMZ CJOE POF QBSBNFUFS BOE DBO POMZ BDDFQU
POF BSHVNFOU 'VODUJPOT UIBU SFRVJSF NVMUJQMF BSHVNFOUT
IBWF NVMUJQMF OFTUFE IFBET 8IFO ZPV BQQMZ JU PODF BOE
FMJNJOBUF UIF ƶSTU MFǒNPTU
IFBE UIF OFYU POF JT BQQMJFE BOE
TP PO 5IJT GPSNVMBUJPO XBT PSJHJOBMMZ EJTDPWFSFE CZ .PTFT
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

4DI¶OƶOLFM JO UIF T CVU XBT MBUFS SFEJTDPWFSFE BOE OBNFE


BǒFS )BTLFMM $VSSZ BOE JT DPNNPOMZ DBMMFE DVSSZJOH
8IBU XF NFBO CZ UIJT EFTDSJQUJPO JT UIBU UIF GPMMPXJOH

ᅶԧԨԧԨ
JT B DPOWFOJFOU TIPSUIBOE GPS UXP OFTUFE MBNCEBT POF GPS
FBDI BSHVNFOU ԧ BOE Ԩ


ᅶԧ ᅶԨԧԨ

8IFO ZPV BQQMZ UIF ƶSTU BSHVNFOU ZPVƊSF CJOEJOH ԧ FMJNJ


OBUJOH UIF PVUFS MBNCEB BOE IBWF ᅶԨԧԨ XJUI Y CFJOH XIBUFWFS
UIF PVUFS MBNCEB XBT CPVOE UP
5P USZ UP NBLF UIJT B MJUUMF NPSF DPODSFUF MFUƊT TVQQPTF
UIBU XF BQQMZ UIFTF MBNCEBT UP TQFDJƶD WBMVFT 'JSTU B TJNQMF
FYBNQMF XJUI UIF JEFOUJUZ GVODUJPO

 ᅶԧԧ

 ᅶԧԧ


 <ԧ ੃ >

 

/PX MFUƊT MPPL BU B ƌNVMUJQMFƍ BSHVNFOU MBNCEB

 ᅶԧԨԧԨ
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 ᅶԧԨԧԨ
 

 ᅶԧ ᅶԨԧԨ

 

 <ԧ ੃ >

 ᅶԨԨ


 <Ԩ ੃ >

  

5IBU XBTOƊU UPP JOUFSFTUJOH CFDBVTF JUƊT MJLF OFTUFE JEFOUJUZ


GVODUJPOT 8F DBOƊU NFBOJOHGVMMZ BQQMZ B  UP B  -FUƊT USZ
TPNFUIJOH EJƵFSFOU

 ᅶԧԨԧԨ

 ᅶԧԨԧԨ
ᅶԩԐ


 ᅶԧ ᅶԨԧԨ

ᅶԩԐ


 <ԧ ੃ ᅶԩԐ
>

 ᅶԨ ᅶԩԐ
Ԩ


 <Ԩ ੃ >

 ᅶԩԐ
 8F TUJMM DBO BQQMZ UIJT POF NPSF UJNF
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 <ԩ ੃ > #VU UIFSF JT OP ԩ JO UIF CPEZ PG UIF GVODUJPO TP


UIFSF JT OPXIFSF UP QVU B  8F FMJNJOBUF UIF IFBE BOE
UIF ƶOBM SFTVMU JT

 Ԑ

*UƊT NPSF DPNNPO JO BDBEFNJD MBNCEB DBMDVMVT NBUFSJBMT


UP SFGFS UP BCTUSBDU WBSJBCMFT SBUIFS UIBO DPODSFUF WBMVFT 5IF
QSPDFTT PG CFUB SFEVDUJPO JT UIF TBNF SFHBSEMFTT 5IF MBNCEB
DBMDVMVT JT B QSPDFTT PS NFUIPE MJLF B HBNF XJUI B GFX TJN
QMF SVMFT GPS USBOTGPSNJOH MBNCEBT CVU OP TQFDJƶD NFBOJOH
8FƊWF KVTU JOUSPEVDFE DPODSFUF WBMVFT UP NBLF UIF SFEVDUJPO
TPNFXIBU FBTJFS UP TFF
5IF OFYU FYBNQMF VTFT POMZ BCTUSBDU WBSJBCMFT %VF UP BM
QIB FRVJWBMFODF ZPV TPNFUJNFT TFF FYQSFTTJPOT JO MBNCEB
DBMDVMVT MJUFSBUVSF TVDI BT

ᅶԧԨԧԧԨ
ᅶԧԧԨ
ᅶԧԧԩ

5IF TVCTUJUVUJPO QSPDFTT DBO CFDPNF B UBOHMF PG ԧT UIBU BSF


OPU UIF TBNF ԧ CFDBVTF FBDI XBT CPVOE CZ B EJƵFSFOU IFBE 5P
IFMQ NBLF UIF SFEVDUJPO FBTJFS UP SFBE XFƊSF HPJOH UP VTF EJG
GFSFOU WBSJBCMFT JO FBDI BCTUSBDUJPO CVU JUƊT XPSUI FNQIBTJ[JOH
UIBU UIF OBNF PG UIF WBSJBCMF UIF MFUUFS
IBT OP NFBOJOH PS
TJHOJƶDBODF

 ᅶԧԨԩԧԩ Ԩԩ

ᅶԜԝԜ
ᅶԟԟ

$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 ᅶԧᅶԨᅶԩԧԩ Ԩԩ

ᅶԜᅶԝԜ
ᅶԟԟ

8FƊWF OPU SFEVDFE PS BQQMJFE BOZUIJOH IFSF KVTU NBEF


UIF DVSSZJOH FYQMJDJU

 ᅶԨᅶԩ ᅶԜᅶԝԜ
ԩ Ԩԩ

ᅶԟԟ

0VS ƶSTU SFEVDUJPO TUFQ XBT UP BQQMZ UIF PVUFSNPTU MBNCEB


XIJDI XBT CJOEJOH UIF ԧ UP UIF ƶSTU BSHVNFOU ᅶԜᅶԝԜ


 ᅶԩ ᅶԜᅶԝԜ
ԩ
ᅶԟԟ
ԩ

8F BQQMJFE UIF Ԩ BOE SFQMBDFE UIF TJOHMF PDDVSSFODF PG


Ԩ XJUI UIF OFYU BSHVNFOU UIF UFSN ᅶԟԟ 5IF PVUFSNPTU
MBNCEB CJOEJOH ԩ JT BU UIJT QPJOU JSSFEVDJCMF CFDBVTF JU
IBT OP BSHVNFOU UP BQQMZ UP 8IBU SFNBJOT JT UP HP JOTJEF
UIF UFSNT POF MBZFS BU B UJNF VOUJM XF ƶOE TPNFUIJOH
SFEVDJCMF

 ᅶԩ ᅶԝԩ
ᅶԟԟ
ԩ

8F DBO BQQMZ UIF MBNCEB CJOEJOH Ԝ UP UIF BSHVNFOU ԩ


8F LFFQ TFBSDIJOH GPS UFSNT XF DBO BQQMZ 5IF OFYU UIJOH
XF DBO BQQMZ JT UIF MBNCEB CJOEJOH ԝ UP UIF MBNCEB UFSN
ᅶԟԟ
ԩ


 ᅶԩԩ
*O UIF ƶOBM TUFQ UIF SFEVDUJPO UBLFT B UVSO UIBU NJHIU MPPL
TMJHIUMZ PEE )FSF UIF PVUFSNPTU MFǒNPTU SFEVDJCMF UFSN
JT ᅶԝԩ BQQMJFE UP UIF FOUJSFUZ PG ᅶԟԟ
ԩ
 "T XF TBX JO
BO FYBNQMF BCPWF JU EPFTOƊU NBUUFS XIBU ԝ HPU CPVOE UP
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

ᅶԝԩ VODPOEJUJPOBMMZ UPTTFT UIF BSHVNFOU BOE SFUVSOT ԩ


4P XF BSF MFǒ XJUI BO JSSFEVDJCMF MBNCEB FYQSFTTJPO

*OUFSNJTTJPO &RVJWBMFODF &YFSDJTFT


8FƊMM HJWF ZPV B MBNCEB FYQSFTTJPO ,FFQJOH JO NJOE CPUI
BMQIB FRVJWBMFODF BOE IPX NVMUJQMF IFBET BSF OFTUFE DIPPTF
BO BOTXFS UIBU JT FRVJWBMFOU UP UIF MJTUFE MBNCEB UFSN

 ᅶԧԨԧԩ

B
ᅶԧԩԧԩ
C
ᅶԜԝԜԩ
D
ᅶԩ ᅶԧԧԩ

 ᅶԧԨԧԧԨ

B
ᅶԜԝԜԝԟ
C
ᅶԧ ᅶԨԧԨ

D
ᅶԐ ᅶԑԐԐԑ

 ᅶԧԨԩԩԧ

B
ᅶԧ ᅶԨ ᅶԩԩ

C
ᅶԣԞԢԢԣ
D
ᅶԜԝԟԜԝ
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 &WBMVBUJPO JT TJNQMJƶDBUJPO


5IFSF BSF NVMUJQMF OPSNBM GPSNT JO MBNCEB DBMDVMVT CVU IFSF
XIFO XF SFGFS UP OPSNBM GPSN XF NFBO CFUB OPSNBM GPSN #FUB
OPSNBM GPSN JT XIFO ZPV DBOOPU CFUB SFEVDF BQQMZ MBNCEBT UP
BSHVNFOUT
UIF UFSNT BOZ GVSUIFS 5IJT DPSSFTQPOET UP B GVMMZ
FWBMVBUFE FYQSFTTJPO PS JO QSPHSBNNJOH B GVMMZ FYFDVUFE
QSPHSBN 5IJT JT JNQPSUBOU UP LOPX TP UIBU ZPV LOPX XIFO
ZPVƊSF EPOF FWBMVBUJOH BO FYQSFTTJPO *UƊT BMTP WBMVBCMF UP IBWF
BO BQQSFDJBUJPO GPS FWBMVBUJPO BT B GPSN PG TJNQMJƶDBUJPO XIFO
ZPV HFU UP UIF )BTLFMM DPEF BT XFMM
%POƊU CF JOUJNJEBUFE CZ DBMMJOH UIF SFEVDFE GPSN PG BO
FYQSFTTJPO JUT OPSNBM GPSN 8IFO ZPV XBOU UP TBZ ƌ ƍ EP ZPV
TBZ  FBDI UJNF PS EP ZPV KVTU TBZ  5IF FYQSFTTJPO
 JT OPU GVMMZ FWBMVBUFE CFDBVTF UIF EJWJTJPO GVODUJPO
IBT OPU CFFO GVMMZ BQQMJFE UXP BSHVNFOUT
TP JU DPVME CF
SFEVDFE PS FWBMVBUFE *O PUIFS XPSET UIFSFƊT B TJNQMFS GPSN
JU DBO CF SFEVDFE UP ƈ UIF OVNCFS UXP 5IF OPSNBM GPSN
UIFSFGPSF JT 
5IF QPJOU JT UIBU JG ZPV IBWF B GVODUJPO TVDI BT 
TBUVSBUFE
BMM BSHVNFOUT BQQMJFE
CVU ZPV IBWFOƊU ZFU TJNQMJƶFE JU UP
UIF ƶOBM SFTVMU UIFO JU JT OPU GVMMZ FWBMVBUFE NFSFMZ BQQMJFE
"QQMJDBUJPO JT XIBU NBLFT FWBMVBUJPOTJNQMJƶDBUJPO QPTTJCMF
4JNJMBSMZ UIF OPSNBM GPSN PG UIF GPMMPXJOH JT 

 
੟ 
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

8F DBOOPU SFEVDF UIF OVNCFS  BOZ GVSUIFS 5IFSF BSF


OP NPSF GVODUJPOT UIBU XF DBO CFUB SFEVDF /PSNBM GPSN KVTU
NFBOT UIFSF JT OPUIJOH MFǒ UIBU DBO CF SFEVDFE
5IF JEFOUJUZ GVODUJPO ᅶԧԧ JT GVMMZ SFEVDFE UIBU JT JO OPS
NBM GPSN
CFDBVTF JU IBTOƊU ZFU CFFO BQQMJFE UP BOZUIJOH )PX
FWFS ᅶԧԧ
ԩ JT OPU JO CFUB OPSNBM GPSN CFDBVTF UIF JEFOUJUZ
GVODUJPO IBTOƊU CFFO BQQMJFE UP B GSFF WBSJBCMF ԩ BOE IBTOƊU
CFFO SFEVDFE *G XF EJE SFEVDF JU UIF ƶOBM SFTVMU JO CFUB
OPSNBM GPSN XPVME CF ԩ

 $PNCJOBUPST
" DPNCJOBUPS JT B MBNCEB UFSN XJUI OP GSFF WBSJBCMFT $PNCJ
OBUPST BT UIF OBNF TVHHFTUT TFSWF POMZ UP DPNCJOF UIF BSHV
NFOUT UIFZ BSF HJWFO
4P UIF GPMMPXJOH BSF DPNCJOBUPST CFDBVTF FWFSZ UFSN JO UIF
CPEZ PDDVST JO UIF IFBE

 ᅶԧԧ
ԧ JT UIF POMZ WBSJBCMF BOE JT CPVOE CFDBVTF JU JT CPVOE CZ
UIF FODMPTJOH MBNCEB

 ᅶԧԨԧ

 ᅶԧԨԩԧԩ Ԩԩ

"OE UIF GPMMPXJOH BSF OPU CFDBVTF UIFSFƊT POF PS NPSF GSFF
WBSJBCMFT
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 ᅶԨԧ
)FSF Ԩ JT CPVOE JU PDDVST JO UIF IFBE PG UIF MBNCEB
CVU
ԧ JT GSFF

 ᅶԧԧԩ
ԧ JT CPVOE BOE JT VTFE JO UIF CPEZ CVU ԩ JT GSFF

8F XPOƊU IBWF B MPU UP TBZ BCPVU DPNCJOBUPST QFS TF 5IF


QPJOU JT UP DBMM PVU B TQFDJBM DMBTT PG MBNCEB FYQSFTTJPOT UIBU
DBO POMZ DPNCJOF UIF BSHVNFOUT JU JT HJWFO XJUIPVU JOKFDUJOH
BOZ OFX WBMVFT PS SBOEPN EBUB

 %JWFSHFODF
/PU BMM SFEVDJCMF MBNCEB UFSNT SFEVDF OFBUMZ UP B CFUB OPSNBM
GPSN 5IJT JTOƊU CFDBVTF UIFZƊSF BMSFBEZ GVMMZ SFEVDFE CVU
SBUIFS CFDBVTF UIFZ EJWFSHF %JWFSHFODF IFSF NFBOT UIBU UIF
SFEVDUJPO QSPDFTT OFWFS UFSNJOBUFT PS FOET 3FEVDJOH UFSNT
TIPVME PSEJOBSJMZ DPOWFSHF UP CFUB OPSNBM GPSN BOE EJWFS
HFODF JT UIF PQQPTJUF PG DPOWFSHFODF PS OPSNBM GPSN )FSFƊT
BO FYBNQMF PG B MBNCEB UFSN DBMMFE PNFHB UIBU EJWFSHFT

 ᅶԧԧԧ
ᅶԧԧԧ

ԧ JO UIF ƶSTU MBNCEBƊT IFBE CFDPNFT UIF TFDPOE MBNCEB

 <ԧ ੃ ᅶԧԧԧ
>ԧԧ

6TJOH <ԥԐԡ ੃ Ԕԧԟԡ> UP EFOPUF XIBU ԧ IBT CFFO CPVOE UP


$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 ᅶԧԧԧ
ᅶԧԧԧ

4VCTUJUVUJOH ᅶԧԧԧ
GPS FBDI PDDVSFODF PG ԧ 8FƊSF CBDL
UP XIFSF XF TUBSUFE BOE UIJT SFEVDUJPO QSPDFTT OFWFS FOET
ƈ XF DBO TBZ PNFHB EJWFSHFT

5IJT NBUUFST JO QSPHSBNNJOH CFDBVTF UFSNT UIBU EJWFSHF


BSF UFSNT UIBU EPOƊU QSPEVDF BO BOTXFS PS NFBOJOHGVM SFTVMU
6OEFSTUBOEJOH XIBU XJMM UFSNJOBUF NFBOT VOEFSTUBOEJOH XIBU
QSPHSBNT XJMM EP VTFGVM XPSL BOE SFUVSO UIF BOTXFS XF XBOU
8FƊMM DPWFS UIJT JEFB NPSF MBUFS

 4VNNBSZ
5IF NBJO QPJOUT ZPV TIPVME UBLF BXBZ GSPN UIJT DIBQUFS BSF

Ƒ 'VODUJPOBM QSPHSBNNJOH JT CBTFE PO FYQSFTTJPOT UIBU JO


DMVEF WBSJBCMFT PS DPOTUBOU WBMVFT FYQSFTTJPOT DPNCJOFE
XJUI PUIFS FYQSFTTJPOT BOE GVODUJPOT

Ƒ 'VODUJPOT IBWF B IFBE BOE B CPEZ BOE BSF UIPTF FYQSFT


TJPOT UIBU DBO CF BQQMJFE UP BSHVNFOUT BOE SFEVDFE PS
FWBMVBUFE UP B SFTVMU

Ƒ 7BSJBCMFT NBZ CF CPVOE JO UIF GVODUJPO EFDMBSBUJPO BOE


FWFSZ UJNF B CPVOE WBSJBCMF TIPXT VQ JO B GVODUJPO JU IBT
UIF TBNF WBMVF

Ƒ "MM GVODUJPOT UBLF POF BSHVNFOU BOE SFUVSO POF SFTVMU


$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

Ƒ 'VODUJPOT BSF B NBQQJOH PG B TFU PG JOQVUT UP B TFU PG


PVUQVUT (JWFO UIF TBNF JOQVU UIFZ BMXBZT SFUVSO UIF
TBNF SFTVMU

5IFTF UIJOHT BMM BQQMZ UP )BTLFMM BT UIFZ EP UP BOZ QVSF


GVODUJPOBM MBOHVBHFT CFDBVTF TFNBOUJDBMMZ )BTLFMM JT B MBNCEB
DBMDVMVT )BTLFMM JT B UZQFE MBNCEB DBMDVMVT ƈ NPSF PO UZQFT
MBUFS ƈ XJUI B MPU PG TVSGBDFMFWFM EFDPSBUJPO TQSJOLMFE PO UPQ
UP NBLF JU FBTJFS GPS IVNBOT UP XSJUF CVU UIF TFNBOUJDT PG UIF
DPSF MBOHVBHF BSF UIF TBNF BT UIF MBNCEB DBMDVMVT 5IBU JT
UIF NFBOJOH PG )BTLFMM QSPHSBNT JT DFOUFSFE BSPVOE FWBMVBU
JOH FYQSFTTJPOT SBUIFS UIBO FYFDVUJOH JOTUSVDUJPOT BMUIPVHI
)BTLFMM IBT B XBZ UP FYFDVUF JOTUSVDUJPOT UPP 8F XJMM TUJMM
CF NBLJOH SFGFSFODF UP UIF MBNCEB DBMDVMVT XIFO XF XSJUF
BCPVU BMM UIF MBUFS BQQBSFOUMZ WFSZ DPNQMFY UPQJDT GVODUJPO
DPNQPTJUJPO NPOBET QBSTFS DPNCJOBUPST %POƊU XPSSZ JG ZPV
EPOƊU LOPX UIPTF XPSET ZFU *G ZPV VOEFSTUPPE UIJT DIBQUFS
ZPV IBWF UIF GPVOEBUJPO ZPV OFFE UP VOEFSTUBOE UIFN BMM

 $IBQUFS &YFSDJTFT


8FƊSF HPJOH UP EP UIF GPMMPXJOH FYFSDJTFT B CJU EJƵFSFOUMZ UIBO
XIBU ZPVƊMM TFF JO UIF SFTU PG UIF CPPL BT XF XJMM CF QSPWJEJOH
TPNF BOTXFST BOE FYQMBOBUJPOT GPS UIF RVFTUJPOT CFMPX
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

$PNCJOBUPST %FUFSNJOF JG FBDI PG UIF GPMMPXJOH BSF DPNCJ


OBUPST PS OPU

 ᅶԧԧԧԧ

 ᅶԧԨԩԧ

 ᅶԧԨԩԧԨ ԩԧ

 ᅶԧԨԩԧԨ ԩԧԨ

 ᅶԧԨԧԨ ԩԧԨ

/PSNBM GPSN PS EJWFSHF %FUFSNJOF JG FBDI PG UIF GPMMPXJOH


DBO CF SFEVDFE UP B OPSNBM GPSN PS JG UIFZ EJWFSHF

 ᅶԧԧԧԧ

 ᅶԩԩԩ
ᅶԨԨԨ

 ᅶԧԧԧԧ
ԩ

#FUB SFEVDF &WBMVBUF UIBU JT CFUB SFEVDF


FBDI PG UIF GPM
MPXJOH FYQSFTTJPOT UP OPSNBM GPSN 8F TUSPOHMZ SFDPNNFOE
XSJUJOH PVU UIF TUFQT PO QBQFS XJUI B QFODJM PS QFO

 ᅶԐԑԒԒԑԐ
ԩԩ ᅶԦԥԦ

 ᅶԧᅶԨԧԨԨ
ᅶԐԐ
ԑ

 ᅶԨԨ
ᅶԧԧԧ
ᅶԩԩԠ

$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 ᅶԩԩ
ᅶԩԩԩ
ᅶԩԩԨ

)JOU BMQIB FRVJWBMFODF

 ᅶԧᅶԨԧԨԨ
ᅶԨԨ
Ԩ

 ᅶԐԐԐ
ᅶԑԑԐ
Ԓ

 ᅶԧԨԩԧԩ Ԩԩ

ᅶԧԩ
ᅶԧԐ

$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 "OTXFST
1MFBTF OPUF "U UIJT UJNF UIJT JT UIF POMZ DIBQUFS JO UIF CPPL GPS
XIJDI XF IBWF QSPWJEFE BOTXFST 8F QSPWJEF UIFN IFSF EVF
UP UIF JNQPSUBODF PG CFJOH BCMF UP DIFDL ZPVS VOEFSTUBOEJOH
PG UIJT NBUFSJBM BOE UIF SFMBUJWF EJƸDVMUZ PG DIFDLJOH BOTXFST
UIBU ZPV QSPCBCMZ XSPUF CZ IBOE JO B OPUFCPPL

$PNCJOBUPST

 ᅶԧԧԧԧ JT JOEFFE B DPNCJOBUPS JU SFGFST POMZ UP UIF WBSJBCMF


Y XIJDI JT JOUSPEVDFE BT BO BSHVNFOU

 ᅶԧԨԩԧ JT OPU B DPNCJOBUPS UIF WBSJBCMF [ XBT OPU JOUSP


EVDFE BT BO BSHVNFOU BOE JT UIVT B GSFF WBSJBCMF

 ᅶԧԨԩԧԨ ԩԧ
JT B DPNCJOBUPS BMM UFSNT BSF CPVOE 5IF IFBE
JT ᅶԧԨԩ BOE UIF CPEZ JT ԧԨ ԩԧ
 /POF PG UIF BSHVNFOUT JO
UIF IFBE IBWF CFFO BQQMJFE TP JUƊT JSSFEVDJCMF 5IF WBSJ
BCMFT Y Z BOE [ BSF BMM CPVOE JO UIF IFBE BOE BSF OPU GSFF
5IJT NBLFT UIF MBNCEB B DPNCJOBUPS  OP PDDVSSFODFT PG
GSFF WBSJBCMFT

 ᅶԧԨԩԧԨ ԩԧԨ
JT B DPNCJOBUPS 5IF MBNCEB IBT UIF IFBE
ᅶԧԨԩ BOE UIF CPEZ ԧԨ ԩԧԨ
 "HBJO OPOF PG UIF BSHVNFOUT
IBWF CFFO BQQMJFE TP JUƊT JSSFEVDJCMF "MM UIBU JT EJƵFSFOU
JT UIBU UIF CPVOE WBSJBCMF Z JT SFGFSFODFE UXJDF SBUIFS
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

UIBO PODF 5IFSF BSF TUJMM OP GSFF WBSJBCMFT TP UIJT JT BMTP B


DPNCJOBUPS

 ᅶԧԨԧԨ ԩԧԨ
JT OPU B DPNCJOBUPS [ JT GSFF /PUF UIBU [ JTOƊU
CPVOE JO UIF IFBE

/PSNBM GPSN PS EJWFSHF

 ᅶԧԧԧԧ EPFTOƊU EJWFSHF IBT OP GVSUIFS SFEVDUJPO TUFQT *G


JU IBE CFFO BQQMJFE UP JUTFMG JU XPVME EJWFSHF CVU CZ JUTFMG
EPFT OPU BT JU JT BMSFBEZ JO OPSNBM GPSN

 ᅶԩԩԩ
ᅶԨԨԨ
EJWFSHFT JU OFWFS SFBDIFT B QPJOU XIFSF UIF
SFEVDUJPO JT EPOF 5IJT JT UIF PNFHB UFSN XF TIPXFE ZPV
FBSMJFS KVTU XJUI EJƵFSFOU OBNFT GPS UIF CJOEJOHT *UƊT
BMQIB FRVJWBMFOU UP ᅶԧԧԧ
ᅶԧԧԧ


 ᅶԧԧԧԧ
ԩ EPFTOƊU EJWFSHF JU SFEVDFT UP ԩԩԩ

#FUB SFEVDF 5IF GPMMPXJOH BSF FWBMVBUFE JO OPSNBM PSEFS XIJDI


JT XIFSF UFSNT JO UIF PVUFSNPTU BOE MFǒNPTU QPTJUJPOT HFU
FWBMVBUFE BQQMJFE
ƶSTU 5IJT NFBOT UIBU JG BMM UFSNT BSF JO
UIF PVUFSNPTU QPTJUJPO OPOF BSF OFTUFE
UIFO JUƊT MFǒUPSJHIU
BQQMJDBUJPO PSEFS

 ᅶԐԑԒԒԑԐ
ԩԩ ᅶԦԥԦ

ᅶԐᅶԑᅶԒԒԑԐ
ԩ
ԩ ᅶԦᅶԥԦ

ᅶԑᅶԒԒԑԩ
ԩ
ᅶԦᅶԥԦ

$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

ᅶԒԒԩԩ
ᅶԦᅶԥԦ

ᅶԦᅶԥԦ
ԩ
ԩ
ᅶԥԩ
ԩ

 ᅶԧᅶԨԧԨԨ
ᅶԐԐ
ԑ
ᅶԨ ᅶԐԐ
ԨԨ
ԑ

ᅶԐԐ
ԑ
ԑ
ԑԑ

 ᅶԨԨ
ᅶԧԧԧ
ᅶԩԩԠ

ᅶԧԧԧ
ᅶԩԩԠ

ᅶԩԩԠ
ᅶԩԩԠ

ᅶԩԩԠ
Ԡ

ԠԠ

 ᅶԩԩ
ᅶԩԩԩ
ᅶԩԩԨ

ᅶԩԩԩ
ᅶԩԩԨ

ᅶԩԩԨ
ᅶԩԩԨ

ᅶԩԩԨ
Ԩ

ԨԨ

 ᅶԧᅶԨԧԨԨ
ᅶԨԨ
Ԩ
ᅶԨ ᅶԨԨ
ԨԨ
Ԩ

ᅶԨԨ
Ԩ
Ԩ
ԨԨ
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 ᅶԐԐԐ
ᅶԑԑԐ
Ԓ
ᅶԑԑԐ
ᅶԑԑԐ
Ԓ
ᅶԑԑԐ
Ԑ
Ԓ
ԐԐԒ

 4UFQT XF UPPL

B
ᅶԧԨԩԧԩ Ԩԩ

ᅶԧԩ
ᅶԧԐ

C
ᅶԧᅶԨᅶԩԧԩ Ԩԩ

ᅶԧԩ
ᅶԧԐ

D
ᅶԨᅶԩ ᅶԧԩ
ԩ Ԩԩ

ᅶԧԐ

E
ᅶԩ ᅶԧԩ
ԩ
ᅶԧԐ
ԩ

F
ᅶԩԩ ᅶԧԐ
ԩ

G
ᅶԩԩԐ
5IF ԩ OPUBUJPO BMMPXT VT UP EJTUJOHVJTI UXP
WBSJBCMFT OBNFE ԩ UIBU DBNF GSPN EJƵFSFOU QMBDFT
0OF JT CPVOE CZ UIF ƶSTU IFBE UIF TFDPOE JT B GSFF
WBSJBCMF JO UIF TFDPOE MBNCEB FYQSFTTJPO

)PX XF HPU UIFSF TUFQ CZ TUFQ

B
0VS FYQSFTTJPO XFƊMM SFEVDF
C
"EE UIF JNQMJFE MBNCEBT UP JOUSPEVDF FBDI BSHVNFOU
D
"QQMZ UIF MFǒNPTU ԧ BOE CJOE JU UP ᅶԧԩ
SFOBNF
MFǒNPTU ԩ UP ԩ GPS DMBSJUZ UP BWPJE DPOGVTJPO XJUI UIF
PUIFS [ )FSFBǒFS ƌ[ƍ JT FYDMVTJWFMZ UIF [ JO ᅶԧԩ

E
"QQMZ Ԩ JU HFUT CPVOE UP ᅶԧԐ

$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

F
$BOƊU BQQMZ [ UP BOZUIJOH FWBMVBUJPO TUSBUFHZ JT OPS
NBM PSEFS TP MFǒNPTU PVUFSNPTU JT UIF PSEFS PG UIF
EBZ 0VS MFǒNPTU PVUFSNPTU MBNCEB IBT OP SFNBJO
JOH BSHVNFOUT UP CF BQQMJFE TP XF OPX FYBNJOF UIF
UFSNT OFTUFE XJUIJO UP TFF JG UIFZ BSF JO OPSNBM GPSN
ᅶԧԩ
HFUT BQQMJFE UP ԩ UPTTFT UIF ԩ BXBZ BOE SFUVSOT
ԩ ԩ JT OPX CFJOH BQQMJFE UP ᅶԧԐ
ԩ


G
$BOOPU SFEVDF ԩ GVSUIFS JUƊT GSFF BOE XF LOPX OPUI
JOH TP XF HP JOTJEF ZFU BOPUIFS OFTUJOH BOE SFEVDF
ᅶԧԐ
ԩ

 ᅶԧԐ HFUT BQQMJFE UP ԩ CVU UPTTFT JU BXBZ


BOE SFUVSOT UIF GSFF WBSJBCMF Ԑ 5IF Ԑ JT OPX QBSU PG
UIF CPEZ PG UIBU FYQSFTTJPO "MM PG PVS UFSNT BSF JO
OPSNBM PSEFS OPX

 %FƶOJUJPOT
 5IF MBNCEB JO MBNCEB DBMDVMVT JT UIF HSFFL MFUUFS ᅶ VTFE
UP JOUSPEVDF PS BCTUSBDU BSHVNFOUT GPS CJOEJOH JO BO
FYQSFTTJPO

 " MBNCEB BCTUSBDUJPO JT BO BOPOZNPVT GVODUJPO PS MBNCEB


UFSN
ᅶԧԧ 

5IF IFBE PG UIF FYQSFTTJPO ᅶԧ BCTUSBDUT PVU UIF UFSN


ԧ  8F DBO BQQMZ JU UP BOZ ԧ BOE SFDPNQVUF EJƵFSFOU
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

SFTVMUT GPS FBDI ԧ XF BQQMJFE UIF MBNCEB UP

 "QQMJDBUJPO JT IPX POF FWBMVBUFT PS SFEVDFT MBNCEBT UIJT


CJOET UIF BSHVNFOU UP XIBUFWFS UIF MBNCEB XBT BQQMJFE
UP $PNQVUBUJPOT BSF QFSGPSNFE JO MBNCEB DBMDVMVT CZ
BQQMZJOH MBNCEBT UP BSHVNFOUT VOUJM ZPV SVO PVU PG BS
HVNFOUT UP BQQMZ MBNCEBT UP
ᅶԧԧ

5IJT FYBNQMF SFEVDFT UP  UIF JEFOUJUZ ᅶԧԧ XBT BQQMJFE
UP UIF WBMVF  ԧ XBT CPVOE UP  BOE UIF MBNCEBƊT CPEZ
JT KVTU ԧ TP JU KVTU LJDLT UIF  PVU *O B TFOTF BQQMZJOH UIF
ᅶԧԧ DPOTVNFE JU 8F SFEVDFE UIF BNPVOU PG TUSVDUVSF XF
IBE

 -BNCEB DBMDVMVT JT B GPSNBM TZTUFN GPS FYQSFTTJOH QSP


HSBNT JO UFSNT PG BCTUSBDUJPO BOE BQQMJDBUJPO

 /PSNBM PSEFS JT B DPNNPO FWBMVBUJPO TUSBUFHZ JO MBNCEB


DBMDVMJ /PSNBM PSEFS NFBOT FWBMVBUJOH JF BQQMZJOH PS
CFUB SFEVDJOH
UIF MFǒNPTU PVUFSNPTU MBNCEBT ƶSTU FWBM
VBUJOH UFSNT OFTUFE XJUIJO BǒFS ZPVƊWF SVO PVU PG BSHV
NFOUT UP BQQMZ /PSNBM PSEFS JTOƊU IPX )BTLFMM DPEF JT
FWBMVBUFE  JUƊT DBMMCZOFFE JOTUFBE 8FƊMM FYQMBJO UIJT NPSF
MBUFS "OTXFST UP UIF FWBMVBUJPO FYFSDJTFT XFSF XSJUUFO JO
OPSNBM PSEFS
$)"15&3  "/:5)*/( '30. "-.045 /05)*/( 

 'PMMPXVQ SFTPVSDFT


5IFTF BSF PQUJPOBM BOE JOUFOEFE POMZ UP PƵFS TVHHFTUJPOT PO
IPX ZPV NJHIU EFFQFO ZPVS VOEFSTUBOEJOH PG UIF QSFDFEJOH
UPQJD 0SEFSFE BQQSPYJNBUFMZ GSPN NPTU BQQSPBDIBCMF UP
NPTU UIPSPVHI

 3BVM 3PKBT " 5VUPSJBM *OUSPEVDUJPO UP UIF -BNCEB $BMDV


MVT
http://www.inf.fu-berlin.de/lehre/WS03/alpi/lambda.pdf

 )FOL #BSFOESFHU &SJL #BSFOETFO *OUSPEVDUJPO UP


-BNCEB $BMDVMVT
http://www.cse.chalmers.se/research/group/logic/
TypesSS05/Extra/geuvers.pdf

 +FBO:WFT (JSBSE 1 5BZMPS :WFT -BGPO 1SPPGT BOE 5ZQFT


http://www.paultaylor.eu/stable/prot.pdf
$IBQUFS 

)FMMP )BTLFMM

'VODUJPOT BSF CFBDPOT PG


DPOTUBODZ JO B TFB PG
UVSNPJM

.JLF )BNNPOE


$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

 )FMMP )BTLFMM


8FMDPNF UP ZPVS ƶSTU TUFQ JO MFBSOJOH )BTLFMM #FGPSF ZPV CF
HJO XJUI UIF NBJO DPVSTF PG UIJT CPPL ZPV XJMM OFFE UP JOTUBMM
UIF OFDFTTBSZ UPPMT JO PSEFS UP DPNQMFUF UIF FYFSDJTFT BT ZPV
XPSL UISPVHI UIF CPPL "U UIJT UJNF XF SFDPNNFOE JOTUBMMJOH
4UBDL XIJDI XJMM JOTUBMM ()$ )BTLFMM UIF JOUFSBDUJWF FOWJSPO
NFOU DBMMFE ()$J BOE B QSPKFDU CVJME UPPM BOE EFQFOEFODZ
NBOBHFS BMM BU PODF
:PV DBO ƶOE UIF JOTUBMMBUJPO JOTUSVDUJPOT POMJOF BU http://
docs.haskellstack.org/en/stable/README/ BOE UIFSF JT BMTP HSFBU
EPDVNFOUBUJPO UIBU DBO IFMQ ZPV HFU TUBSUFE VTJOH 4UBDL :PV
DBO BMTP ƶOE JOTUBMMBUJPO JOTUSVDUJPOT BU https://github.com/
bitemyapp/learnhaskell BOE UIFSF ZPV XJMM BMTP ƶOE BEWJDF PO
MFBSOJOH )BTLFMM BOE MJOLT UP NPSF FYFSDJTFT UIBU NBZ TVQQMF
NFOU XIBU ZPVƊSF EPJOH XJUI UIJT CPPL
5IF SFTU PG UIJT DIBQUFS XJMM BTTVNF UIBU ZPV IBWF DPNQMFUFE
UIF JOTUBMMBUJPO BOE BSF SFBEZ UP CFHJO XPSLJOH *O UIJT DIBQUFS
ZPV XJMM

Ƒ VTF )BTLFMM DPEF JO UIF JOUFSBDUJWF FOWJSPONFOU BOE BMTP


GSPN TPVSDF ƶMFT

Ƒ VOEFSTUBOE UIF CVJMEJOH CMPDLT PG )BTLFMM FYQSFTTJPOT


BOE GVODUJPOT
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Ƒ MFBSO TPNF GFBUVSFT PG )BTLFMM TZOUBY BOE DPOWFOUJPOT PG


HPPE )BTLFMM TUZMF

Ƒ NPEJGZ TJNQMF GVODUJPOT

 *OUFSBDUJOH XJUI )BTLFMM DPEF


)BTLFMM PƵFST UXP QSJNBSZ XBZT PG XPSLJOH XJUI DPEF 5IF
ƶSTU JT JOQVUUJOH JU EJSFDUMZ JOUP UIF JOUFSBDUJWF FOWJSPONFOU
LOPXO BT ()$J PS UIF 3&1- 5IF TFDPOE JT UZQJOH JU JOUP B
UFYU FEJUPS TBWJOH BOE UIFO MPBEJOH UIBU TPVSDF ƶMF JOUP ()$J
5IJT TFDUJPO PƵFST BO JOUSPEVDUJPO UP FBDI NFUIPE

6TJOH UIF 3&1-


3&1- JT BO BDSPOZN TIPSU GPS SFBEFWBMQSJOU MPPQ 3&1-T BSF
JOUFSBDUJWF QSPHSBNNJOH FOWJSPONFOUT XIFSF ZPV DBO JOQVU
DPEF IBWF JU FWBMVBUFE BOE TFF UIF SFTVMU 5IFZ PSJHJOBUFE
XJUI -JTQ CVU BSF OPX DPNNPO UP NPEFSO QSPHSBNNJOH
MBOHVBHFT JODMVEJOH )BTLFMM
"TTVNJOH ZPVƊWF DPNQMFUFE ZPVS JOTUBMMBUJPO ZPV TIPVME
CF BCMF UP PQFO ZPVS UFSNJOBM PS DPNNBOE QSPNQU UZQF ghci
PS stack ghci IJU FOUFS BOE TFF TPNFUIJOH MJLF UIF GPMMPXJOH

GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help



*G ZPV IBWF JOTUBMMFE ()$ PVUTJEF PG 4UBDL UIFO ZPV TIPVME CF BCMF UP PQFO JU XJUI
KVTU UIF ghci DPNNBOE CVU JG ZPVS POMZ ()$ JOTUBMMBUJPO JT XIBU 4UBDL JOTUBMMFE UIFO ZPV
XJMM OFFE stack ghci
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude>

*G ZPV VTFE stack ghci UIFSF XBT QSPCBCMZ B MPU NPSF TUBSUVQ
UFYU BOE UIF QSPNQU NJHIU CF TPNFUIJOH PUIFS UIBO Prelude
5IBUƊT BMM ƶOF :PV NBZ BMTP IBWF B EJƵFSFOU WFSTJPO PG ()$
"T MPOH BT ZPVS ()$ WFSTJPO JT CFUXFFO  BOE  JU TIPVME
CF DPNQBUJCMF XJUI FWFSZUIJOH JO UIJT CPPL
/PX USZ FOUFSJOH TPNF TJNQMF BSJUINFUJD BU ZPVS QSPNQU

Prelude> 2 + 2
4
Prelude> 7 < 9
True
Prelude> 10 ^ 2
100

*G ZPV DBO FOUFS TJNQMF FRVBUJPOT BU UIF QSPNQU BOE HFU UIF
FYQFDUFE SFTVMUT DPOHSBUVMBUJPOT ƈ ZPV BSF OPX B GVODUJPOBM
QSPHSBNNFS .PSF UP UIF QPJOU ZPVS 3&1- JT XPSLJOH XFMM
BOE ZPV BSF SFBEZ UP QSPDFFE
5P FYJU ()$J VTF UIF DPNNBOE :quit PS :q

8IBU JT 1SFMVEF 1SFMVEF JT B MJCSBSZ PG TUBOEBSE GVODUJPOT


0QFOJOH ()$J PS 4UBDL ()$J BVUPNBUJDBMMZ MPBET UIPTF GVOD
UJPOT TP UIFZ DBO CF VTFE XJUIPVU OFFEJOH UP EP BOZUIJOH TQF

"U UIJT QPJOU JO UIF CPPL ZPV EPOƊU OFFE UP VTF stack ghci CVU JO MBUFS DIBQUFST XIFO
XFƊSF JNQPSUJOH B MPU PG NPEVMFT BOE CVJMEJOH QSPKFDUT JU XJMM CF NVDI NPSF DPOWFOJFOU
UP VTF JU
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

DJBM :PV DBO UVSO 1SFMVEF PƵ BT XF XJMM TIPX ZPV NVDI MBUFS
BOE UIFSF BSF BMUFSOBUJWF 1SFMVEFT UIPVHI XF XPOƊU VTF UIFN
JO UIF CPPL 1SFMVEF JT DPOUBJOFE JO )BTLFMMƊT base QBDLBHF
XIJDI DBO CF GPVOE BU https://www.stackage.org/package/base
:PVƊMM TFF VT NFOUJPO TPNFUJNFT UIBU TPNFUIJOH PS PUIFS JT
ƌJO baseƍ XIJDI NFBOT JUƊT DPOUBJOFE JO UIBU WBTU GPVOEBUJPOBM
QBDLBHF

()$J DPNNBOET
5ISPVHIPVU UIF CPPL XFƊMM CF VTJOH ()$J DPNNBOET TVDI
BT :quit BOE :info JO UIF 3&1- 4QFDJBM DPNNBOET UIBU POMZ
()$J VOEFSTUBOET CFHJO XJUI UIF : DIBSBDUFS :quit JT OPU
)BTLFMM DPEF JUƊT KVTU B ()$J GFBUVSF 8F XJMM TFF NPSF PG
UIFTF DPNNBOET UISPVHIPVU UIF CPPL
8F XJMM QSFTFOU UIFN JO UIF UFYU TQFMMFE PVU CVU UIFZ DBO
HFOFSBMMZ CF BCCSFWJBUFE UP KVTU UIF DPMPO BOE UIF ƶSTU MFUUFS
5IBU JT :quit CFDPNFT :q :info CFDPNFT :i BOE TP GPSUI *UƊT
HPPE UP UZQF UIF XPSE PVU UIF ƶSTU GFX UJNFT ZPV VTF JU UP IFMQ
ZPV SFNFNCFS XIBU UIF BCCSFWJBUJPO TUBOET GPS CVU BǒFS B
GFX NFOUJPOT XF XJMM TUBSU BCCSFWJBUJOH UIFN

8PSLJOH GSPN TPVSDF ƶMFT


"T OJDF BT 3&1-T BSF VTVBMMZ ZPV XBOU UP TUPSF DPEF JO B ƶMF
TP ZPV DBO CVJME JU JODSFNFOUBMMZ "MNPTU BMM OPOUSJWJBM QSP
HSBNNJOH ZPV EP XJMM JOWPMWF FEJUJOH MJCSBSJFT PS BQQMJDBUJPOT
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

NBEF PG OFTUFE EJSFDUPSJFT DPOUBJOJOH ƶMFT XJUI )BTLFMM DPEF


JO UIFN 5IF CBTJD QSPDFTT JT UP IBWF UIF DPEF BOE JNQPSUT
NPSF PO UIBU MBUFS
JO B ƶMF MPBE JU JOUP UIF 3&1- BOE JOUFSBDU
XJUI JU UIFSF BT ZPVƊSF CVJMEJOH NPEJGZJOH BOE UFTUJOH JU
:PVƊMM OFFE B ƶMF OBNFE test.hs 5IF .hs ƶMF FYUFOTJPO EF
OPUFT B )BTLFMM TPVSDF DPEF ƶMF %FQFOEJOH PO ZPVS TFUVQ BOE
UIF XPSLƷPX ZPVƊSF DPNGPSUBCMF XJUI ZPV DBO NBLF B ƶMF CZ
UIBU OBNF BOE UIFO PQFO JU JO ZPVS UFYU FEJUPS PS ZPV DBO PQFO
ZPVS UFYU FEJUPS PQFO B OFX ƶMF BOE UIFO TBWF UIF ƶMF XJUI
UIBU ƶMF OBNF
5IFO FOUFS UIF GPMMPXJOH DPEF JOUP UIF ƶMF BOE TBWF JU

sayHello :: String -> IO ()


sayHello x = putStrLn ("Hello, " ++ x ++ "!")

)FSF :: JT B XBZ UP XSJUF EPXO B UZQF TJHOBUVSF :PV DBO


UIJOL PG JU BT TBZJOH ƌIBT UIF UZQFƍ 4P sayHello IBT UIF UZQF
String -> IO () 5IFTF ƶSTU DIBQUFST BSF GPDVTFE PO TZOUBY
TP JG ZPV EPOƊU VOEFSTUBOE XIBU UZQFT PS UZQF TJHOBUVSFT BSF
UIBUƊT 0, ƈ XF XJMM FYQMBJO UIFN TPPO 'PS OPX LFFQ HPJOH
5IFO JO UIF TBNF EJSFDUPSZ XIFSF ZPVƊWF TUPSFE ZPVS test.hs
ƶMF PQFO ZPVS ghci 3&1- BOE EP UIF GPMMPXJOH

Prelude> :load test.hs


Prelude> sayHello "Haskell"
Hello, Haskell!
Prelude>
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

"ǒFS VTJOH :load UP MPBE ZPVS test.hs UIF sayHello GVODUJPO


JT WJTJCMF JO UIF 3&1- BOE ZPV DBO QBTT JU B TUSJOH BSHVNFOU
TVDI BT ƌ)BTLFMMƍ OPUF UIF RVPUBUJPO NBSLT
BOE TFF UIF PVU
QVU
:PV NBZ OPUJDF UIBU BǒFS MPBEJOH DPEF GSPN B TPVSDF ƶMF
UIF ()$J QSPNQU JT OP MPOHFS Prelude> 5P SFUVSO UP UIF
Prelude> QSPNQU VTF UIF DPNNBOE :m XIJDI JT TIPSU GPS :module
5IJT XJMM VOMPBE UIF ƶMF GSPN ()$J TP UIF DPEF JO UIBU ƶMF
XJMM OP MPOHFS CF JO TDPQF JO ZPVS 3&1-

 6OEFSTUBOEJOH FYQSFTTJPOT


&WFSZUIJOH JO )BTLFMM JT BO FYQSFTTJPO PS EFDMBSBUJPO &YQSFT
TJPOT NBZ CF WBMVFT DPNCJOBUJPOT PG WBMVFT BOEPS GVODUJPOT
BQQMJFE UP WBMVFT &YQSFTTJPOT FWBMVBUF UP B SFTVMU *O UIF DBTF
PG B MJUFSBM WBMVF UIF FWBMVBUJPO JT USJWJBM BT JU POMZ FWBMVBUFT
UP JUTFMG *O UIF DBTF PG BO BSJUINFUJD FRVBUJPO UIF FWBMVBUJPO
QSPDFTT JT UIF QSPDFTT PG DPNQVUJOH UIF PQFSBUPS BOE JUT BS
HVNFOUT BT ZPV NJHIU FYQFDU #VU FWFO UIPVHI OPU BMM PG
ZPVS QSPHSBNT XJMM CF BCPVU EPJOH BSJUINFUJD BMM PG )BTLFMMƊT
FYQSFTTJPOT XPSL JO B TJNJMBS XBZ FWBMVBUJOH UP B SFTVMU JO B
QSFEJDUBCMF USBOTQBSFOU NBOOFS &YQSFTTJPOT BSF UIF CVJMEJOH
CMPDLT PG PVS QSPHSBNT BOE QSPHSBNT UIFNTFMWFT BSF POF CJH
FYQSFTTJPO NBEF PG TNBMMFS FYQSFTTJPOT
8FƊMM DPWFS EFDMBSBUJPOT NPSF MBUFS CVU JU TVƸDFT UP TBZ GPS
OPX UIBU UIFZ BSF UPQMFWFM CJOEJOHT XIJDI BMMPXT VT UP OBNF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

FYQSFTTJPOT 8F DBO UIFO VTF UIPTF OBNFT UP SFGFS UP UIFN


NVMUJQMF UJNFT XJUIPVU DPQZJOH BOE QBTUJOH UIF FYQSFTTJPOT

5IF GPMMPXJOH BSF BMM FYQSFTTJPOT

1
1 + 1
"Icarus"

&BDI DBO CF FYBNJOFE JO UIF ()$J 3&1- CZ FOUFSJOH UIF


DPEF BU UIF QSPNQU UIFO IJUUJOH ƉFOUFSƊ UP TFF UIF SFTVMU PG
FWBMVBUJOH UIF FYQSFTTJPO 5IF OVNFSJD WBMVF  GPS FYBNQMF
IBT OP GVSUIFS SFEVDUJPO TUFQ TP JU TUBOET GPS JUTFMG
*G ZPV IBWFOƊU BMSFBEZ PQFO VQ ZPVS UFSNJOBM BOE HFU ZPVS
3&1- HPJOH UP TUBSU GPMMPXJOH BMPOH XJUI UIF DPEF FYBNQMFT
8IFO XF FOUFS UIJT JOUP ()$J

Prelude> 1
1

8F TFF  QSJOUFE CFDBVTF JU DBOOPU CF SFEVDFE BOZ GVSUIFS


*O UIF OFYU FYBNQMF ()$J SFEVDFT UIF FYQSFTTJPO 1 + 2 UP
 UIFO QSJOUT UIF OVNCFS  5IF SFEVDUJPO UFSNJOBUFT XJUI
UIF WBMVF  CFDBVTF UIFSF BSF OP NPSF UFSNT UP FWBMVBUF

Prelude> 1 + 2
3
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

&YQSFTTJPOT DBO CF OFTUFE JO OVNCFST MJNJUFE POMZ CZ PVS


XJMMJOHOFTT UP UBLF UIF UJNF UP XSJUF UIFN EPXO NVDI MJLF JO
BSJUINFUJD

Prelude> (1 + 2) * 3
9
Prelude> ((1 + 2) * 3) + 100
109

:PV DBO LFFQ FYQBOEJOH PO UIJT OFTUJOH BT NBOZ FYQSFT


TJPOT BT ZPVƊE MJLF BOE FWBMVBUJOH UIFN #VU XF EPOƊU IBWF UP
MJNJU PVSTFMWFT UP FYQSFTTJPOT TVDI BT UIFTF

/PSNBM GPSN 8F TBZ UIBU FYQSFTTJPOT BSF JO OPSNBM GPSN


XIFO UIFSF BSF OP NPSF FWBMVBUJPO TUFQT UIBU DBO CF UBLFO
PS QVU EJƵFSFOUMZ XIFO UIFZƊWF SFBDIFE BO JSSFEVDJCMF GPSN
5IF OPSNBM GPSN PG 1 + 1 JT  8IZ #FDBVTF UIF FYQSFTTJPO 1
+ 1 DBO CF FWBMVBUFE PS SFEVDFE CZ BQQMZJOH UIF BEEJUJPO PQFS
BUPS UP UIF UXP BSHVNFOUT *O PUIFS XPSET 1 + 1 JT B SFEVDJCMF
FYQSFTTJPO XIJMF  JT BO FYQSFTTJPO CVU JT OP MPOHFS SFEVDJCMF
ƈ JU DBOƊU FWBMVBUF JOUP BOZUIJOH PUIFS UIBO JUTFMG 3FEVDJCMF FY
QSFTTJPOT BSF BMTP DBMMFE SFEFYFT 8IJMF XF XJMM HFOFSBMMZ SFGFS
UP UIJT QSPDFTT BT FWBMVBUJPO PS SFEVDUJPO ZPV NBZ BMTP IFBS
JU DBMMFE ƌOPSNBMJ[JOHƍ PS ƌFYFDVUJOHƍ BO FYQSFTTJPO UIPVHI
UIFTF BSF TPNFXIBU JNQSFDJTF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

 'VODUJPOT
&YQSFTTJPOT BSF UIF NPTU CBTJD VOJU PG B )BTLFMM QSPHSBN
BOE GVODUJPOT BSF B TQFDJƶD UZQF PG FYQSFTTJPO 'VODUJPOT JO
)BTLFMM BSF SFMBUFE UP GVODUJPOT JO NBUIFNBUJDT XIJDI JT UP
TBZ UIFZ NBQ BO JOQVU PS TFU PG JOQVUT UP BO PVUQVU " GVODUJPO
JT BO FYQSFTTJPO UIBU JT BQQMJFE UP BO BSHVNFOU BOE BMXBZT
SFUVSOT B SFTVMU #FDBVTF UIFZ BSF CVJMU QVSFMZ PG FYQSFTTJPOT
UIFZ XJMM BMXBZT FWBMVBUF UP UIF TBNF SFTVMU XIFO HJWFO UIF
TBNF WBMVFT
"T JO UIF MBNCEB DBMDVMVT BMM GVODUJPOT JO )BTLFMM UBLF POF
BSHVNFOU BOE SFUVSO POF SFTVMU 5IF XBZ UP UIJOL PG UIJT JT UIBU
JO )BTLFMM XIFO JU TFFNT XF BSF QBTTJOH NVMUJQMF BSHVNFOUT UP
B GVODUJPO XF BSF BDUVBMMZ BQQMZJOH B TFSJFT PG OFTUFE GVODUJPOT
FBDI UP POF BSHVNFOU 5IJT JT DBMMFE DVSSZJOH BOE JU XJMM CF
BEESFTTFE JO HSFBUFS EFUBJM MBUFS
:PV NBZ IBWF OPUJDFE UIBU UIF FYQSFTTJPOT XFƊWF MPPLFE
BU TP GBS VTF MJUFSBM WBMVFT XJUI OP WBSJBCMFT PS BCTUSBDUJPOT
'VODUJPOT BMMPX VT UP BCTUSBDU UIF QBSUT PG DPEF XFƊE XBOU UP
SFVTF GPS EJƵFSFOU MJUFSBM WBMVFT *OTUFBE PG OFTUJOH BEEJUJPO
FYQSFTTJPOT GPS FYBNQMF XF DPVME XSJUF B GVODUJPO UIBU XPVME
BEE UIF WBMVF XF XBOUFE XIFSFWFS XF DBMMFE UIBU GVODUJPO
'PS FYBNQMF TBZ ZPV IBE B CVODI PG TJNQMF FYQSFTTJPOT
ZPV OFFEFE UP NVMUJQMZ CZ  :PV DPVME LFFQ FOUFSJOH UIFN
BT JOEJWJEVBM FYQSFTTJPOT MJLF UIJT
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> (1 + 2) * 3
9
Prelude> (4 + 5) * 3
27
Prelude> (10 + 5) * 3
45

#VU ZPV EPOƊU XBOU UP EP UIBU 'VODUJPOT BSF IPX XF GBDUPS


PVU UIF QBUUFSO JOUP TPNFUIJOH XF DBO SFVTF XJUI EJƵFSFOU JO
QVUT :PV EP UIBU CZ OBNJOH UIF GVODUJPO BOE JOUSPEVDJOH BO
JOEFQFOEFOU WBSJBCMF BT UIF BSHVNFOU UP UIF GVODUJPO 'VOD
UJPOT DBO BMTP BQQFBS JO UIF FYQSFTTJPOT UIBU GPSN UIF CPEJFT
PG PUIFS GVODUJPOT PS CF VTFE BT BSHVNFOUT UP GVODUJPOT KVTU
BT BOZ PUIFS WBMVF DBO CF
*O UIJT DBTF XF IBWF B TFSJFT PG FYQSFTTJPOT UIBU XF XBOU UP
NVMUJQMZ CZ  -FUƊT UIJOL JO UFSNT PG B GVODUJPO XIBU QBSU JT
DPNNPO UP BMM UIF FYQSFTTJPOT 8IBU QBSU WBSJFT 8F LOPX XF
IBWF UP HJWF GVODUJPOT B OBNF BOE BQQMZ UIFN UP BO BSHVNFOU
TP XIBU DPVME XF DBMM UIJT GVODUJPO BOE XIBU TPSU PG BSHVNFOU
NJHIU XF BQQMZ JU UP
5IF DPNNPO QBUUFSO JT UIF * 3 CJU 5IF QBSU UIBU WBSJFT
JT UIF BEEJUJPO FYQSFTTJPO CFGPSF JU TP XF XJMM NBLF UIBU B
WBSJBCMF 8F XJMM OBNF PVS GVODUJPO BOE BQQMZ JU UP UIF WBSJBCMF
8IFO XF JOQVU B WBMVF GPS UIF WBSJBCMF PVS GVODUJPO XJMM
FWBMVBUF UIBU NVMUJQMZ JU CZ  BOE SFUVSO B SFTVMU *O UIF OFYU
TFDUJPO XF XJMM GPSNBMJ[F UIJT JOUP B QSPQFS )BTLFMM GVODUJPO
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

%FƶOJOH GVODUJPOT
'VODUJPO EFƶOJUJPOT BMM TIBSF B GFX UIJOHT JO DPNNPO 'JSTU
UIFZ TUBSU XJUI UIF OBNF PG UIF GVODUJPO 5IJT JT GPMMPXFE CZ
UIF GPSNBM QBSBNFUFST PG UIF GVODUJPO TFQBSBUFE POMZ CZ XIJUF
TQBDF /FYU UIFSF JT BO FRVBM TJHO XIJDI FYQSFTTFT FRVBMJUZ PG
UIF UFSNT 'JOBMMZ UIFSF JT BO FYQSFTTJPO UIBU JT UIF CPEZ PG
UIF GVODUJPO BOE DBO CF FWBMVBUFE UP SFUVSO B WBMVF
%FƶOJOH GVODUJPOT JO B OPSNBM )BTLFMM TPVSDF DPEF ƶMF BOE
JO ()$J BSF B MJUUMF EJƵFSFOU 5P JOUSPEVDF EFƶOJUJPOT PG WBMVFT
PS GVODUJPOT JO ()$J ZPV NVTU VTF let XIJDI MPPLT MJLF UIJT

Prelude> let triple x = x * 3

*O B TPVSDF ƶMF XF XPVME FOUFS JU MJLF UIJT

triple x = x * 3

-FUƊT FYBNJOF FBDI QBSU PG UIBU

triple x = x * 3
-- [1] [2] [3] [ 4 ]

*O QSBDUJDF UIF UFSNT ƉBSHVNFOUƊ BOE ƉQBSBNFUFSƊ BSF PǒFO VTFE JOUFSDIBOHFBCMZ
CVU UIFSF JT B EJƵFSFODF Ɖ"SHVNFOUƊ QSPQFSMZ SFGFST UP UIF WBMVF T
UIBU BSF QBTTFE UP UIF
GVODUJPOƊT QBSBNFUFST XIFO UIF GVODUJPO JT BQQMJFE OPU UP UIF WBSJBCMFT UIBU SFQSFTFOU
UIFN JO UIF GVODUJPO EFƶOJUJPO PS UIPTF JO UIF UZQF TJHOBUVSF
 4FF UIF EFƶOJUJPOT BU UIF
FOE PG UIF DIBQUFS GPS NPSF JOGPSNBUJPO
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

 5IJT JT UIF OBNF PG UIF GVODUJPO XF BSF EFƶOJOH JU JT B


GVODUJPO EFDMBSBUJPO /PUF UIBU JU CFHJOT XJUI B MPXFSDBTF
MFUUFS

 5IJT JT UIF QBSBNFUFS PG UIF GVODUJPO 5IF QBSBNFUFST PG


PVS GVODUJPO DPSSFTQPOE UP UIF ƌIFBEƍ PG B MBNCEB BOE
CJOE WBSJBCMFT UIBU BQQFBS JO UIF CPEZ FYQSFTTJPO

 5IF  JT VTFE UP EFƶOF PS EFDMBSF


WBMVFT BOE GVODUJPOT
3FNJOEFS UIJT JT OPU IPX XF UFTU GPS FRVBMJUZ CFUXFFO
UXP WBMVFT JO )BTLFMM

 5IJT JT UIF CPEZ PG UIF GVODUJPO BO FYQSFTTJPO UIBU DPVME


CF FWBMVBUFE JG UIF GVODUJPO JT BQQMJFE UP B WBMVF *G triple
JT BQQMJFE UIF BSHVNFOU JUƊT BQQMJFE UP XJMM CF UIF WBMVF
UP XIJDI UIF ԧ JT CPVOE )FSF UIF FYQSFTTJPO x * 3 DPOTUJ
UVUFT UIF CPEZ PG UIF GVODUJPO 4P JG ZPV IBWF BO FYQSFT
TJPO MJLF triple 6 ԧ JT CPVOE UP  4JODF ZPVƊWF BQQMJFE UIF
GVODUJPO ZPV DBO BMTP SFQMBDF UIF GVMMZ BQQMJFE GVODUJPO
XJUI JUT CPEZ BOE CPVOE BSHVNFOUT

$BQJUBMJ[BUJPO NBUUFST 'VODUJPO OBNFT TUBSU XJUI MPXFSDBTF


MFUUFST 4PNFUJNFT GPS DMBSJUZ JO GVODUJPO OBNFT ZPV NBZ
XBOU DBNFM$BTF TUZMF BOE UIBU JT HPPE TUZMF QSPWJEFE UIF ƶSTU
MFUUFS SFNBJOT MPXFSDBTF
7BSJBCMFT NVTU BMTP CFHJO XJUI MPXFSDBTF MFUUFST
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

1MBZJOH XJUI UIF USJQMF GVODUJPO 'JSTU USZ FOUFSJOH UIF triple
GVODUJPO EJSFDUMZ JOUP UIF 3&1- VTJOH let /PX DBMM UIF GVOD
UJPO CZ OBNF BOE JOUSPEVDF B OVNFSJD WBMVF GPS UIF ԧ BSHV
NFOU

Prelude> triple 2
6

/FYU FOUFS UIF TFDPOE WFSTJPO UIF POF XJUIPVU let


JOUP B
TPVSDF ƶMF BOE TBWF UIF ƶMF -PBE JU JOUP ()$J VTJOH UIF :load
PS :l DPNNBOE 0ODF JUƊT MPBEFE ZPV DBO DBMM UIF GVODUJPO
BU UIF QSPNQU VTJOH UIF GVODUJPO OBNF triple GPMMPXFE CZ
B OVNFSJD WBMVF KVTU BT ZPV EJE JO UIF 3&1- FYBNQMF BCPWF
5SZ VTJOH EJƵFSFOU WBMVFT GPS ԧ ƈ JOUFHFS WBMVFT PS PUIFS BSJUI
NFUJD FYQSFTTJPOT 5IFO USZ DIBOHJOH UIF GVODUJPO JUTFMG JO
UIF TPVSDF ƶMF BOE SFMPBEJOH JU UP TFF XIBU DIBOHFT

 &WBMVBUJPO
8IFO XF UBML BCPVU FWBMVBUJOH BO FYQSFTTJPO XFƊSF UBMLJOH
BCPVU SFEVDJOH UIF UFSNT VOUJM UIF FYQSFTTJPO SFBDIFT JUT TJN
QMFTU GPSN 0ODF B UFSN IBT SFBDIFE JUT TJNQMFTU GPSN XF TBZ
UIBU JU JT JSSFEVDJCMF PS ƶOJTIFE FWBMVBUJOH 6TVBMMZ XF DBMM
UIJT B WBMVF )BTLFMM VTFT B OPOTUSJDU FWBMVBUJPO TPNFUJNFT
DBMMFE ƌMB[Z FWBMVBUJPOƍ
TUSBUFHZ XIJDI EFGFST FWBMVBUJPO PG
UFSNT VOUJM UIFZƊSF GPSDFE CZ PUIFS UFSNT SFGFSSJOH UP UIFN
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

8F XJMM SFUVSO UP UIJT DPODFQU TFWFSBM UJNFT UISPVHIPVU UIF


CPPL BT JU UBLFT UJNF UP GVMMZ VOEFSTUBOE
7BMVFT BSF JSSFEVDJCMF CVU BQQMJDBUJPOT PG GVODUJPOT UP BS
HVNFOUT BSF SFEVDJCMF 3FEVDJOH BO FYQSFTTJPO NFBOT FWBMV
BUJOH UIF UFSNT VOUJM ZPVƊSF MFǒ XJUI B WBMVF "T JO UIF MBNCEB
DBMDVMVT BQQMJDBUJPO JT FWBMVBUJPO BQQMZJOH B GVODUJPO UP BO
BSHVNFOU BMMPXT FWBMVBUJPO PS SFEVDUJPO
7BMVFT BSF FYQSFTTJPOT CVU DBOOPU CF SFEVDFE GVSUIFS 7BM
VFT BSF B UFSNJOBM QPJOU PG SFEVDUJPO

1
"Icarus"

5IF GPMMPXJOH FYQSFTTJPOT DBO CF SFEVDFE FWBMVBUFE JG ZPV


XJMM
UP B WBMVF

1 + 1
2 * 3 + 1

&BDI DBO CF FWBMVBUFE JO UIF 3&1- XIJDI SFEVDFT UIF FY


QSFTTJPOT BOE UIFO QSJOUT XIBU JU SFEVDFE UP
-FUƊT HFU CBDL UP PVS triple GVODUJPO $BMMJOH UIF GVODUJPO
CZ OBNF BOE BQQMZJOH JU UP BO BSHVNFOU NBLFT JU B SFEVDJCMF
FYQSFTTJPO *O B QVSF GVODUJPOBM MBOHVBHF MJLF )BTLFMM XF DBO
SFQMBDF BQQMJDBUJPOT PG GVODUJPOT XJUI UIFJS EFƶOJUJPOT BOE HFU
UIF TBNF SFTVMU KVTU MJLF JO NBUI "T B SFTVMU XIFO XF TFF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

triple 2

8F DBO LOPX UIBU TJODF USJQMF JT EFƶOFE BT x = x * 3 UIF


FYQSFTTJPO JT FRVJWBMFOU UP

triple 2
-- [triple x = x * 3; x:= 2]
2 * 3
6

8FƊWF BQQMJFE triple UP UIF WBMVF  BOE UIFO SFEVDF UIF


FYQSFTTJPO UP UIF ƶOBM SFTVMU  0VS FYQSFTTJPO triple 2 JT JO
DBOPOJDBM PS OPSNBM GPSN XIFO JU SFBDIFT UIF OVNCFS  CFDBVTF
UIF WBMVF  IBT OP SFNBJOJOH SFEVDJCMF FYQSFTTJPOT
)BTLFMM EPFTOƊU FWBMVBUF FWFSZUIJOH UP DBOPOJDBM PS OPSNBM
GPSN CZ EFGBVMU *OTUFBE JU POMZ FWBMVBUFT UP XFBL IFBE OPS
NBM GPSN 8)/'
CZ EFGBVMU 8FƊMM HFU JOUP UIF EFUBJMT PG XIBU
UIBU NFBOT TPNFXIBU MBUFS JO UIF CPPL 'PS OPX XF XBOU UP
FNQIBTJ[F UIBU )BTLFMMƊT OPOTUSJDU FWBMVBUJPO NFBOT OPU FW
FSZUIJOH XJMM HFU SFEVDFE UP JUT JSSFEVDJCMF GPSN JNNFEJBUFMZ
TP UIJT

(\f -> (1, 2 + f)) 2

SFEVDFT UP UIF GPMMPXJOH JO 8)/'

(1, 2 + 2)
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

5IJT SFQSFTFOUBUJPO JT BO BQQSPYJNBUJPO CVU UIF LFZ QPJOU


IFSF JT UIBU 2 + 2 JT OPU FWBMVBUFE UP 4 VOUJM UIF MBTU QPTTJCMF
NPNFOU

&YFSDJTFT $PNQSFIFOTJPO $IFDL


 (JWFO UIF GPMMPXJOH MJOFT PG DPEF BT UIFZ NJHIU BQQFBS
JO B TPVSDF ƶMF IPX XPVME ZPV DIBOHF UIFN UP VTF UIFN
EJSFDUMZ JO UIF 3&1-

half x = x / 2

square x = x * x

 8SJUF POF GVODUJPO UIBU DBO BDDFQU POF BSHVNFOU BOE


XPSL GPS BMM UIF GPMMPXJOH FYQSFTTJPOT #F TVSF UP OBNF
UIF GVODUJPO

3.14 * (5 * 5)
3.14 * (10 * 10)
3.14 * (2 * 2)
3.14 * (4 * 4)

 5IFSF JT B WBMVF JO 1SFMVEF DBMMFE pi 3FXSJUF ZPVS GVOD


UJPO UP VTF pi JOTUFBE PG 
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

 *OƶY PQFSBUPST


'VODUJPOT JO )BTLFMM EFGBVMU UP QSFƶY TZOUBY NFBOJOH UIBU UIF
GVODUJPO CFJOH BQQMJFE JT BU UIF CFHJOOJOH PG UIF FYQSFTTJPO
SBUIFS UIBO UIF NJEEMF 8F TBX UIBU XJUI PVS triple GVODUJPO
BOE XF TFF JU XJUI TUBOEBSE GVODUJPOT TVDI BT UIF JEFOUJUZ PS
id GVODUJPO 5IJT GVODUJPO KVTU SFUVSOT XIBUFWFS WBMVF JU JT
HJWFO BT BO BSHVNFOU

Prelude> id 1
1

8IJMF UIJT JT UIF EFGBVMU TZOUBY GPS GVODUJPOT OPU BMM GVOD
UJPOT BSF QSFƶY 5IFSF BSF B HSPVQ PG PQFSBUPST TVDI BT UIF
BSJUINFUJD PQFSBUPST XFƊWF CFFO VTJOH UIBU BSF JOEFFE GVOD
UJPOT UIFZ BQQMZ UP BSHVNFOUT UP QSPEVDF BO PVUQVU
CVU BQ
QFBS CZ EFGBVMU JO BO JOƶY QPTJUJPO
0QFSBUPST BSF GVODUJPOT XIJDI DBO CF VTFE JO JOƶY TUZMF
"MM PQFSBUPST BSF GVODUJPOT OPU BMM GVODUJPOT BSF PQFSBUPST
8IJMF triple BOE id BSF QSFƶY GVODUJPOT OPU PQFSBUPST
UIF +
GVODUJPO JT BO JOƶY PQFSBUPS

Prelude> 1 + 1
2

/PX XFƊMM USZ B GFX PUIFS NBUIFNBUJDBM PQFSBUPST


$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> 100 + 100


200
Prelude> 768395 * 21356345
16410108716275
Prelude> 123123 / 123
1001.0
Prelude> 476 - 36
440
Prelude> 10 / 4
2.5

:PV DBO TPNFUJNFT VTF GVODUJPOT JOƶY TUZMF XJUI B TNBMM


DIBOHF JO TZOUBY

Prelude> 10 `div` 4
2
Prelude> div 10 4
2

"OE ZPV DBO VTF JOƶY PQFSBUPST JO QSFƶY GBTIJPO CZ XSBQ


QJOH UIFN JO QBSFOUIFTFT

Prelude> (+) 100 100


200
Prelude> (*) 768395 21356345
16410108716275
Prelude> (/) 123123 123
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

1001.0

*G UIF GVODUJPO OBNF JT BMQIBOVNFSJD JU JT B QSFƶY GVODUJPO


CZ EFGBVMU BOE OPU BMM QSFƶY GVODUJPOT DBO CF NBEF JOƶY *G
UIF OBNF JT B TZNCPM JU JT JOƶY CZ EFGBVMU CVU DBO CF NBEF
QSFƶY CZ XSBQQJOH JU JO QBSFOUIFTFT

"TTPDJBUJWJUZ BOE QSFDFEFODF


"T ZPV NBZ SFNFNCFS GSPN ZPVS NBUI DMBTTFT UIFSFƊT B EF
GBVMU BTTPDJBUJWJUZ BOE QSFDFEFODF UP UIF JOƶY PQFSBUPST (*)
(+) (-) BOE (/)
8F DBO BTL ()$J GPS JOGPSNBUJPO TVDI BT BTTPDJBUJWJUZ BOE
QSFDFEFODF PG PQFSBUPST BOE GVODUJPOT CZ VTJOH UIF :info DPN
NBOE 8IFO ZPV BTL ()$J GPS UIF :info BCPVU BO PQFSBUPS
PS GVODUJPO JU QSPWJEFT UIF UZQF JOGPSNBUJPO *U BMTP UFMMT ZPV
XIFUIFS JUƊT BO JOƶY PQFSBUPS BOE JG JU JT JUT BTTPDJBUJWJUZ BOE
QSFDFEFODF -FUƊT UBML BCPVU UIBU BTTPDJBUJWJUZ BOE QSFDFEFODF
CSJFƷZ 8F XJMM FMJEF UIF UZQF JOGPSNBUJPO BOE TP GPSUI GPS
OPX
)FSFƊT XIBU UIF DPEF JO 1SFMVEF TBZT GPS (*) (+) BOE (-) BU
UJNF PG XSJUJOH

'PS QFPQMF XIP MJLF OJUQJDLZ EFUBJMT ZPV DBOOPU NBLF B QSFƶY GVODUJPO JOUP BO JOƶY
GVODUJPO VTJOH CBDLUJDLT UIFO XSBQ UIBU JO QBSFOUIFTFT BOE NBLF JU JOUP B QSFƶY GVODUJPO
8FƊSF OPU DMFBS XIZ ZPVƊE XBOU UP EP UIBU BOZXBZ $VU JU PVU
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

:info (*)
infixl 7 *
-- [1] [2] [3]

:info (+) (-)


infixl 6 +

infixl 6 -

 infixl NFBOT JUƊT BO JOƶY PQFSBUPS MFǒ BTTPDJBUJWF

  JT UIF QSFDFEFODF IJHIFS JT BQQMJFE ƶSTU PO B TDBMF PG




 *OƶY GVODUJPO OBNF JO UIJT DBTF NVMUJQMJDBUJPO

5IF JOGPSNBUJPO BCPVU BEEJUJPO BOE TVCUSBDUJPO UFMM VT UIFZ


BSF CPUI MFǒBTTPDJBUJWF JOƶY PQFSBUPST XJUI UIF TBNF QSFDF
EFODF 

-FUƊT QMBZ XJUI QBSFOUIFTFT BOE TFF XIBU JU NFBOT UIBU UIFTF
BTTPDJBUF UP UIF MFǒ $POUJOVF UP GPMMPX BMPOH XJUI UIF DPEF
WJB UIF 3&1-
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

-- this
2 * 3 * 4

-- is evaluated as if it was
(2 * 3) * 4
-- Because of left-associativity from infixl

)FSFƊT BO FYBNQMF PG B SJHIUBTTPDJBUJWF JOƶY PQFSBUPS

Prelude> :info (^)


infixr 8 ^
-- [1] [2] [3]

 infixr NFBOT JOƶY PQFSBUPS SJHIU BTTPDJBUJWF

  JT UIF QSFDFEFODF )JHIFS QSFDFEFODF JOEJDBUFE CZ


IJHIFS OVNCFST JT BQQMJFE ƶSTU TP UIJT JT IJHIFS QSFDF
EFODF UIBO NVMUJQMJDBUJPO 
BEEJUJPO PS TVCUSBDUJPO
CPUI 


 *OƶY GVODUJPO OBNF JO UIJT DBTF FYQPOFOUJBUJPO

*U XBT IBSE UP UFMM XJUI NVMUJQMJDBUJPO XIZ BTTPDJBUJWJUZ NBU


UFSFE CFDBVTF NVMUJQMJDBUJPO JT BTTPDJBUJWF 4P TIJǒJOH UIF
QBSFOUIFTFT BSPVOE OFWFS DIBOHFT UIF SFTVMU &YQPOFOUJBUJPO
IPXFWFS JT OPU BTTPDJBUJWF BOE UIVT NBLFT B QSJNF DBOEJEBUF
GPS EFNPOTUSBUJOH MFǒ WT SJHIU BTTPDJBUJWJUZ
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> 2 ^ 3 ^ 4
2417851639229258349412352
Prelude> 2 ^ (3 ^ 4)
2417851639229258349412352
Prelude> (2 ^ 3) ^ 4
4096

"T ZPV DBO TFF BEEJOH QBSFOUIFTFT TUBSUJOH GSPN UIF SJHIU
IBOE TJEF PG UIF FYQSFTTJPO XIFO UIF PQFSBUPS JT SJHIUBTTPDJBUJWF
EPFTOƊU DIBOHF BOZUIJOH )PXFWFS JG XF QBSFOUIFTJ[F GSPN
UIF MFǕ XF HFU B EJƵFSFOU SFTVMU XIFO UIF FYQSFTTJPO JT FWBMV
BUFE
:PVS JOUVJUJPOT BCPVU QSFDFEFODF BTTPDJBUJWJUZ BOE QBSFO
UIFTJ[BUJPO GSPN NBUI DMBTTFT XJMM HFOFSBMMZ IPME JO )BTLFMM

2 + 3 * 4

(2 + 3) * 4

8IBUƊT UIF EJƵFSFODF CFUXFFO UIFTF UXP 8IZ BSF UIFZ


EJƵFSFOU

&YFSDJTFT 1BSFOUIFTFT BOE "TTPDJBUJPO


#FMPX BSF TPNF QBJST PG GVODUJPOT UIBU BSF BMJLF FYDFQU GPS
QBSFOUIFTJ[BUJPO 3FBE UIFN DBSFGVMMZ BOE EFDJEF JG UIF QBSFO
UIFTFT DIBOHF UIF SFTVMUT PG UIF GVODUJPO $IFDL ZPVS XPSL JO
()$J
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

 B
8 + 7 * 9
C
(8 + 7) * 9

 B
perimeter x y = (x * 2) + (y * 2)
C
perimeter x y = x * 2 + y * 2

 B
f x = x / 2 + 9
C
f x = x / (2 + 9)

 %FDMBSJOH WBMVFT


5IF PSEFS PG EFDMBSBUJPOT JO B TPVSDF DPEF ƶMF EPFTOƊU NBUUFS
CFDBVTF ()$J MPBET UIF FOUJSF ƶMF BU PODF TP JU LOPXT BMM UIF
WBMVFT UIBU IBWF CFFO EFƶOFE 0O UIF PUIFS IBOE XIFO ZPV
FOUFS UIFN POF CZ POF JOUP UIF 3&1- UIF PSEFS EPFT NBUUFS
'PS FYBNQMF XF DBO EFDMBSF B TFSJFT PG FYQSFTTJPOT JO UIF
3&1- MJLF UIJT

Prelude> let y = 10
Prelude> let x = 10 * 5 + y
Prelude> let myResult = x * 5

"T XF TBX BCPWF XJUI UIF triple GVODUJPO XF IBWF UP VTF


let UP EFDMBSF TPNFUIJOH JO UIF 3&1-
8F DBO OPX UZQF UIF OBNFT PG UIF WBMVFT BOE IJU FOUFS UP
TFF UIFJS WBMVFT
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> x
60
Prelude> y
10
Prelude> myResult
300

5P EFDMBSF UIF TBNF WBMVFT JO B ƶMF TVDI BT learn.hs XF


XSJUF UIF GPMMPXJOH

-- learn.hs

module Learn where


-- First, we declare the name of our module so
-- it can be imported by name in a project.
-- We won't be doing a project of this size
-- for a while yet.

x = 10 * 5 + y

myResult = x * 5

y = 10

3FNFNCFS NPEVMF OBNFT BSF DBQJUBMJ[FE VOMJLF WBSJBCMF


OBNFT "MTP JO UIJT WBSJBCMF OBNF XFƊWF VTFE DBNFM$BTF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

UIF ƶSTU MFUUFS JT TUJMM MPXFSDBTF CVU XF VTF BO VQQFSDBTF UP


EFMJOFBUF B XPSE CPVOEBSZ GPS SFBEBCJMJUZ

5SPVCMFTIPPUJOH
*U JT FBTZ UP NBLF NJTUBLFT JO UIF QSPDFTT PG UZQJOH learn.hs
JOUP ZPVS FEJUPS 8FƊMM MPPL BU B GFX DPNNPO NJTUBLFT JO
UIJT TFDUJPO 0OF UIJOH UP LFFQ JO NJOE JT UIBU JOEFOUBUJPO PG
)BTLFMM DPEF JT TJHOJƶDBOU BOE DBO DIBOHF UIF NFBOJOH PG UIF
DPEF *ODPSSFDU JOEFOUBUJPO PG DPEF DBO BMTP CSFBL ZPVS DPEF
3FNJOEFS VTF TQBDFT OPU UBCT UP JOEFOU ZPVS TPVSDF DPEF
*O HFOFSBM XIJUFTQBDF JT TJHOJƶDBOU JO )BTLFMM &ƸDJFOU
VTF PG XIJUFTQBDF NBLFT UIF TZOUBY NPSF DPODJTF 5IJT DBO
UBLF TPNF HFUUJOH VTFE UP JG ZPVƊWF CFFO XPSLJOH JO BOPUIFS
QSPHSBNNJOH MBOHVBHF 8IJUFTQBDF JT PǒFO UIF POMZ NBSL PG
B GVODUJPO DBMM VOMFTT QBSFOUIFTFT BSF OFDFTTBSZ EVF UP DPO
ƷJDUJOH QSFDFEFODF 5SBJMJOH XIJUFTQBDF UIBU JT FYUSBOFPVT
XIJUFTQBDF BU UIF FOE PG MJOFT PG DPEF JT DPOTJEFSFE CBE TUZMF

*O TPVSDF DPEF ƶMFT JOEFOUBUJPO PǒFO SFQMBDFT TZOUBDUJD


NBSLFST MJLF DVSMZ CSBDLFUT TFNJDPMPOT BOE QBSFOUIFTFT 5IF
CBTJD SVMF JT UIBU DPEF UIBU JT QBSU PG BO FYQSFTTJPO TIPVME CF
JOEFOUFE VOEFS UIF CFHJOOJOH PG UIBU FYQSFTTJPO FWFO XIFO
UIF CFHJOOJOH PG UIF FYQSFTTJPO JT OPU BU UIF MFǒNPTU NBSHJO
'VSUIFSNPSF QBSUT PG UIF FYQSFTTJPO UIBU BSF HSPVQFE TIPVME
CF JOEFOUFE UP UIF TBNF MFWFM 'PS FYBNQMF JO B CMPDL PG DPEF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

JOUSPEVDFE CZ let PS do ZPV NJHIU TFF TPNFUIJOH MJLF UIJT

let
x = 3
y = 4

-- or

let x = 3
y = 4

-- Note that this code won't work directly in a


-- source file without embedding in a
-- top-level declaration

/PUJDF UIBU UIF UXP EFƶOJUJPOT UIBU BSF QBSU PG UIF FYQSFTTJPO
MJOF VQ JO FJUIFS DBTF *U JT JODPSSFDU UP XSJUF

let x = 3
y = 4

-- or

let
x = 3
y = 4
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

*G ZPV IBWF BO FYQSFTTJPO UIBU IBT NVMUJQMF QBSUT ZPVS


JOEFOUBUJPO XJMM GPMMPX B QBUUFSO MJLF UIJT

foo x =
let y = x * 2
z = x ^ 2
in 2 * y * z

/PUJDF UIBU UIF EFƶOJUJPOT PG Ԩ BOE ԩ MJOF VQ BOE UIF EFG


JOJUJPOT PG let BOE in BSF BMTP BMJHOFE "T ZPV XPSL UISPVHI UIF
CPPL USZ UP QBZ DBSFGVM BUUFOUJPO UP UIF JOEFOUBUJPO QBUUFSOT BT
XF IBWF UIFN QSJOUFE 5IFSF BSF NBOZ DBTFT XIFSF JNQSPQFS
JOEFOUBUJPO XJMM BDUVBMMZ DBVTF DPEF OPU UP XPSL *OEFOUBUJPO
DBO FBTJMZ HP XSPOH JO B DPQZBOEQBTUF KPC BT XFMM
"MTP XIFO ZPV XSJUF )BTLFMM DPEF XF SFJUFSBUF IFSF UIBU
ZPV XBOU UP VTF TQBDFT BOE OPU UBCT GPS JOEFOUBUJPO 6TJOH
TQBDFT XJMM TBWF ZPV B OPOUSJWJBM BNPVOU PG HSJFG .PTU UFYU
FEJUPST DBO CF DPOƶHVSFE UP VTF POMZ TQBDFT GPS JOEFOUBUJPO
TP ZPV NBZ XBOU UP JOWFTUJHBUF IPX UP EP UIBU GPS ZPVST
*G ZPV NBLF B NJTUBLF MJLF CSFBLJOH VQ UIF EFDMBSBUJPO PG ԧ
TVDI UIBU UIF SFTU PG UIF FYQSFTTJPO CFHBO BU UIF CFHJOOJOH PG
UIF OFYU MJOF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

module Learn where


-- First declare the name of our module so it
-- can be imported by name in a project.
-- We won't do this for a while yet.

x = 10
* 5 + y

myResult = x * 5

y = 10

:PV NJHIU TFF BO FSSPS MJLF

Prelude> :l code/learn.hs
[1 of 1] Compiling Learn

code/learn.hs:10:1: parse error on input ‘*’


Failed, modules loaded: none.

/PUF UIBU UIF ƶSTU MJOF PG UIF FSSPS NFTTBHF UFMMT ZPV XIFSF
UIF FSSPS PDDVSSFE code/learn.hs:10:1 JOEJDBUFT UIBU UIF NJT
UBLF JT JO MJOF  DPMVNO  PG UIF OBNFE ƶMF 5IBU DBO NBLF JU
FBTJFS UP ƶOE UIF QSPCMFN UIBU OFFET UP CF ƶYFE 1MFBTF OPUF
UIBU UIF FYBDU MJOF BOE DPMVNO OVNCFST JO ZPVS PXO FSSPS
NFTTBHFT NJHIU CF EJƵFSFOU GSPN PVST EFQFOEJOH PO IPX
ZPVƊWF FOUFSFE UIF DPEF JOUP UIF ƶMF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

5IF XBZ UP ƶY UIJT JT UP FJUIFS QVU JU BMM PO POF MJOF MJLF UIJT

x = 10 * 5 + y

PS UP NBLF DFSUBJO XIFO ZPV CSFBL VQ MJOFT PG DPEF UIBU UIF


TFDPOE MJOF CFHJOT BU MFBTU POF TQBDF GSPN UIF CFHJOOJOH PG
UIBU MJOF FJUIFS PG UIF GPMMPXJOH TIPVME XPSL


x = 10
* 5 + y

-- or

x = 10
* 5 + y

5IF TFDPOE POF MPPLT B MJUUMF CFUUFS (FOFSBMMZ ZPV TIPVME


SFTFSWF CSFBLJOH VQ PG MJOFT GPS XIFO ZPV IBWF DPEF FYDFFEJOH
 DPMVNOT JO XJEUI
"OPUIFS QPTTJCMF FSSPS JT OPU TUBSUJOH B EFDMBSBUJPO BU UIF
CFHJOOJOH MFǒ
DPMVNO PG UIF MJOF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

-- learn.hs

module Learn where

x = 10 * 5 + y

myResult = x * 5

y = 10

4FF UIBU TQBDF CFGPSF ԧ 5IBU XJMM DBVTF BO FSSPS MJLF

Prelude> :l code/learn.hs
[1 of 1] Compiling Learn

code/learn.hs:11:1: parse error on input ‘myResult’


Failed, modules loaded: none.

5IJT NBZ DPOGVTF ZPV BT myResult JT OPU XIFSF ZPV OFFE UP


NPEJGZ ZPVS DPEF 5IF FSSPS JT POMZ BO FYUSBOFPVT TQBDF CVU
BMM EFDMBSBUJPOT JO UIF NPEVMF NVTU TUBSU BU UIF TBNF DPMVNO
5IF DPMVNO UIBU BMM EFDMBSBUJPOT XJUIJO B NPEVMF NVTU TUBSU
JO JT EFUFSNJOFE CZ UIF ƶSTU EFDMBSBUJPO JO UIF NPEVMF *O UIJT
DBTF UIF FSSPS NFTTBHF HJWFT B MPDBUJPO UIBU JT EJƵFSFOU GSPN
XIFSF ZPV TIPVME ƶY UIF QSPCMFN CFDBVTF BMM UIF DPNQJMFS
LOPXT JT UIBU UIF EFDMBSBUJPO PG ԧ NBEF B TJOHMF TQBDF UIF BQ
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

QSPQSJBUF JOEFOUBUJPO GPS BMM EFDMBSBUJPOT XJUIJO UIBU NPEVMF


BOE UIF EFDMBSBUJPO PG myResult CFHBO B DPMVNO UPP FBSMZ
*U JT QPTTJCMF UP ƶY UIJT FSSPS CZ JOEFOUJOH UIF myResult BOE
Ԩ EFDMBSBUJPOT UP UIF TBNF MFWFM BT UIF JOEFOUFE ԧ EFDMBSBUJPO

-- learn.hs

module Learn where

x = 10 * 5 + y

myResult = x * 5

y = 10

)PXFWFS UIJT JT DPOTJEFSFE CBE TUZMF BOE JT OPU TUBOEBSE


)BTLFMM QSBDUJDF 5IFSF JT BMNPTU OFWFS B HPPE SFBTPO UP JOEFOU
BMM ZPVS EFDMBSBUJPOT JO UIJT XBZ CVU OPUJOH UIJT HJWFT VT TPNF
JEFB PG IPX UIF DPNQJMFS JT SFBEJOH UIF DPEF *U JT CFUUFS XIFO
DPOGSPOUFE XJUI BO FSSPS NFTTBHF MJLF UIJT UP NBLF TVSF UIBU
ZPVS ƶSTU EFDMBSBUJPO JT BU UIF MFǒNPTU NBSHJO BOE QSPDFFE
GSPN UIFSF
"OPUIFS QPTTJCMF NJTUBLF JT UIBU ZPV NJHIUƊWF NJTTFE UIF
TFDPOE - JO UIF -- VTFE UP DPNNFOU PVU TPVSDF MJOFT PG DPEF
4P UIJT DPEF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

- learn.hs

module Learn where


-- First declare the name of our module so it
-- can be imported by name in a project.
-- We won't do this for a while yet.

x = 10 * 5 + y

myResult = x * 5

y = 10

XJMM DBVTF UIJT FSSPS

code/learn.hs:7:1: parse error on input ‘module’


Failed, modules loaded: none.

/PUF BHBJO UIBU JU TBZT UIF QBSTF FSSPS PDDVSSFE BU UIF CF
HJOOJOH PG UIF NPEVMF EFDMBSBUJPO CVU UIF JTTVF JT BDUVBMMZ
UIBU - learn.hs IBE POMZ POF - XIFO JU OFFEFE UXP UP GPSN B
TZOUBDUJDBMMZ DPSSFDU )BTLFMM DPNNFOU
/PX XF DBO TFF IPX UP XPSL XJUI DPEF UIBU JT TBWFE JO B
TPVSDF ƶMF GSPN ()$J XJUIPVU NBOVBMMZ DPQZJOH BOE QBTUJOH
UIF EFƶOJUJPOT JOUP PVS 3&1- "TTVNJOH XF PQFO PVS 3&1-
JO UIF TBNF EJSFDUPSZ BT XF IBWF learn.hs TBWFE XF DBO EP UIF
GPMMPXJOH
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> :load learn.hs


[1 of 1] Compiling Learn
Ok, modules loaded: Learn.
Prelude> x
60
Prelude> y
10
Prelude> myResult
300

&YFSDJTFT )FBM UIF 4JDL


5IF GPMMPXJOH DPEF TBNQMFT BSF CSPLFO BOE XPOƊU DPNQJMF
5IF ƶSTU UXP BSF BT ZPV NJHIU FOUFS JOUP UIF 3&1- UIF UIJSE
JT GSPN B TPVSDF ƶMF 'JOE UIF NJTUBLFT BOE ƶY UIFN TP UIBU
UIFZ XJMM

 let area x = 3. 14 * (x * x)

 let double x = b * 2

 x = 7
y = 10
f = x + y
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

 "SJUINFUJD GVODUJPOT JO )BTLFMM


5IJT TFDUJPO XJMM FYQMPSF TPNF CBTJD BSJUINFUJD VTJOH TPNF
DPNNPO PQFSBUPST BOE GVODUJPOT GPS BSJUINFUJD 8FƊMM GPDVT
PO UIF GPMMPXJOH TVCTFU PG UIFN

0QFSBUPS /BNF 1VSQPTFBQQMJDBUJPO


QMVT BEEJUJPO
 NJOVT TVCUSBDUJPO
BTUFSJTL NVMUJQMJDBUJPO
 TMBTI GSBDUJPOBM EJWJTJPO
EJW EJWJEF JOUFHSBM EJWJTJPO SPVOE EPXO
NPE NPEVMP MJLF ƉSFNƊ CVU BǒFS NPEVMBS EJWJTJPO
RVPU RVPUJFOU JOUFHSBM EJWJTJPO SPVOE UPXBSET [FSP
SFN SFNBJOEFS SFNBJOEFS BǒFS EJWJTJPO

"U UIF SJTL PG TUBUJOH UIF PCWJPVT ƌJOUFHSBMƍ EJWJTJPO SFGFST


UP EJWJTJPO PG JOUFHFST #FDBVTF JUƊT JOUFHSBM BOE OPU GSBDUJPOBM
JU UBLFT JOUFHFST BT BSHVNFOUT BOE SFUVSOT JOUFHFST BT SFTVMUT
5IBUƊT XIZ UIF SFTVMUT BSF SPVOEFE
)FSFƊT BO FYBNQMF PG FBDI JO UIF 3&1-

Prelude> 1 + 1
2
Prelude> 1 - 1
0
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> 1 * 1
1
Prelude> 1 / 1
1.0
Prelude> div 1 1
1
Prelude> mod 1 1
0
Prelude> quot 1 1
1
Prelude> rem 1 1
0

:PV XJMM VTVBMMZ XBOU div GPS JOUFHSBM EJWJTJPO VOMFTT ZPV
LOPX XIBU ZPVƊSF EPJOH EVF UP UIF XBZ div BOE quot SPVOE

-- rounds down
Prelude> div 20 (-6)
-4

-- rounds toward zero


Prelude> quot 20 (-6)
-3

"MTP rem BOE mod IBWF TMJHIUMZ EJƵFSFOU VTF DBTFT XFƊMM MPPL
BU mod JO B MJUUMF NPSF EFUBJM EPXO CFMPX 8F XJMM DPWFS (/)
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

JO NPSF EFUBJM JO B MBUFS DIBQUFS BT UIBU XJMM SFRVJSF TPNF


FYQMBOBUJPO PG UZQFT BOE UZQFDMBTTFT

-BXT GPS RVPUJFOUT BOE SFNBJOEFST


1SPHSBNNJOH PǒFO NBLFT VTF PG NPSF EJWJTJPO BOE SFNBJO
EFS GVODUJPOT UIBO TUBOEBSE BSJUINFUJD EPFT BOE JUƊT IFMQGVM UP
CF GBNJMJBS XJUI UIF MBXT BCPVU RVPUSFN BOE EJWNPE 8FƊMM
UBLF B MPPL BU UIPTF IFSF

(quot x y)*y + (rem x y) == x

(div x y)*y + (mod x y) == x

8F XPOƊU XBML UISPVHI B QSPPG FYFSDJTF CVU XF DBO EFNPO


TUSBUF UIFTF MBXT B CJU

(quot x y)*y + (rem x y)

Given x is 10 and y is (-4)

(quot 10 (-4))*(-4) + (rem 10 (-4))

quot 10 (-4) == (-2) and rem 10 (-4) == 2


'SPN -FOOBSU "VHVTUTTPOƊT CMPH http://augustss.blogspot.com/ PS 4UBDL 0WFSƷPX
BOTXFS BU http://stackoverflow.com/a/8111203
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

(-2)*(-4) + (2) == 10

10 == x == yeppers.

*UƊT OPU XPSUI HFUUJOH PWFSMZ JOWFTUFE JO UIF NFBOJOH PG


ƌZFQQFSTƍ UIFSF JU KVTU NFBOT XF HPU UP UIF SFTVMU XF XBOUFE
/PX GPS div BOE mod

(div x y)*y + (mod x y)

Given x is 10 and y is (-4)

(div 10 (-4))*(-4) + (mod 10 (-4))

div 10 (-4) == (-3) and mod 10 (-4) == -2

(-3)*(-4) + (-2) == 10

10 == x == yeppers.

0VS SFTVMU JOEJDBUFT BMM JT XFMM JO UIF XPSME PG JOUFHSBM EJWJ


TJPO

6TJOH ƉNPEƉ
5IJT TFDUJPO JT OPU B GVMM EJTDVTTJPO PG NPEVMBS BSJUINFUJD CVU
XF XBOU UP HJWF NPSF EJSFDUJPO JO IPX UP VTF mod JO HFOFSBM
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

GPS UIPTF XIP NBZ CF VOGBNJMJBS XJUI JU BOE IPX JU XPSLT JO


)BTLFMM TQFDJƶDBMMZ
8FƊWF BMSFBEZ NFOUJPOFE UIBU mod HJWFT UIF SFNBJOEFS PG
B NPEVMBS EJWJTJPO *G ZPVƊSF OPU BMSFBEZ GBNJMJBS XJUI NPE
VMBS EJWJTJPO ZPV NBZ OPU VOEFSTUBOE UIF VTFGVM EJƵFSFODF
CFUXFFO mod BOE rem
.PEVMBS BSJUINFUJD JT B TZTUFN PG BSJUINFUJD GPS JOUFHFST
XIFSF OVNCFST ƌXSBQ BSPVOEƍ VQPO SFBDIJOH B DFSUBJO WBMVF
DBMMFE UIF NPEVMVT *U JT PǒFO FYQMBJOFE JO UFSNT PG B DMPDL
8IFO XF DPVOU UJNF CZ B IPVS DMPDL XF IBWF UP XSBQ
UIF DPVOUJOH BSPVOE UIF  'PS FYBNQMF JG UIF UJNF JT OPX
 BOE ZPV XBOU UP LOPX XIBU UJNF JU XJMM CF  IPVST GSPN
OPX ZPV EPOƊU TJNQMZ BEE   BOE HFU B SFTVMU PG  PƊDMPDL
*OTUFBE ZPV XSBQ UIF DPVOU BSPVOE FWFSZ  IPVST 4P
BEEJOH  IPVST UP  NFBOT UIBU XF BEE  IPVST UP HFU UP
UIF  BOE BU UIF  XF TUBSU PWFS BHBJO BT JG JUƊT  BOE BEE UIF
SFNBJOJOH  IPVST PG PVS  GPS BO BOTXFS PG  5IBU JT 
IPVST BǒFS  JT 
5IJT JT BSJUINFUJD NPEVMP  *O PVS IPVS DMPDL  JT
FRVJWBMFOU UP CPUI JUTFMG BOE UP  TP UIF UJNF BU  JT BMTP
JO TPNF TFOTF  "SJUINFUJD NPEVMP  NFBOT UIBU  JT
CPUI  BOE 
0ǒFO UIJT XJMM HJWF ZPV UIF TBNF BOTXFS UIBU rem EPFT

0CWJPVTMZ XJUI B IPVS DMPDL TVDI B UJNF JT QPTTJCMF IPXFWFS JG XF XFSF TUBSUJOH
GSPN  QN BOE USZJOH UP ƶOE UIF UJNF  IPVST MBUFS UIF BOTXFS XPVME OPU CF 
BN " IPVS DMPDL IBT B EJƵFSFOU NPEVMVT UIBO B IPVS DMPDL
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> mod 15 12
3
Prelude> rem 15 12
3

Prelude> mod 21 12
9
Prelude> rem 21 12
9

Prelude> mod 3 12
3
Prelude> rem 3 12
3

*G ZPVƊSF XPOEFSJOH XIBU UIF EFBM JT XJUI UIF MBTU UXP FY
BNQMFT JUƊT CFDBVTF mod BOE rem DBO POMZ SFQSFTFOU JOUFHSBM
EJWJTJPO *G BMM ZPV IBWF UP XPSL XJUI JT JOUFHFST UIFO EJWJEJOH
B TNBMMFS OVNCFS CZ B MBSHFS OVNCFS SFTVMUT JO BO BOTXFS PG
 XJUI B SFNBJOEFS PG XIBUFWFS UIF TNBMMFS OVNCFS UIF EJWJ
EFOE
JT *G ZPV XBOU UP EJWJEF B TNBMMFS OVNCFS CZ B MBSHFS
OVNCFS BOE SFUVSO B GSBDUJPOBM BOTXFS UIFO ZPV OFFE UP VTF
(/) BOE ZPV XPOƊU IBWF B SFNBJOEFS
-FUƊT TBZ XF OFFE UP XSJUF B GVODUJPO UIBU XJMM EFUFSNJOF
XIBU EBZ PG UIF XFFL JU XBT PS XJMM CF B DFSUBJO OVNCFS PG
EBZT CFGPSF PS BǒFS UIJT POF 'PS PVS QVSQPTFT IFSF XF XJMM
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

BTTJHO B OVNCFS UP FBDI EBZ PG UIF XFFL VTJOH  UP SFQSFTFOU


4VOEBZ 5IFO JG UPEBZ JT .POEBZ BOE XF XBOU UP LOPX XIBU
EBZ PG UIF XFFL JU XJMM CF  EBZT GSPN OPX XF DPVME EP UIJT

Prelude> mod (1 + 23) 7


3

5IF  SFQSFTFOUT .POEBZ UIF DVSSFOU EBZ XIJMF  JT UIF


OVNCFS PG EBZT XFƊSF USZJOH UP BEE 6TJOH mod UP XSBQ JU BSPVOE
UIF  NFBOT JU XJMM SFUVSO B OVNCFS UIBU DPSSFTQPOET UP B EBZ
PG UIF XFFL JO PVS OVNCFSJOH
"OE  EBZT GSPN 4BUVSEBZ XJMM CF 5IVSTEBZ

Prelude> mod (6 + 5) 7
4

8F DBO VTF rem UP EP UIF TBNF UIJOH XJUI BQQBSFOUMZ FRVJW


BMFOU BDDVSBDZ

Prelude> rem (1 + 23) 7


3

)PXFWFS JG XF XBOU UP TVCUSBDU BOE ƶOE PVU XIBU EBZ PG


UIF XFFL JU XBT TPNF OVNCFS PG EBZT BHP UIFO XFƊMM TFF B
EJƵFSFODF -FUƊT USZ BTLJOH JG UPEBZ JT 8FEOFTEBZ 
XIBU
EBZ JU XBT  EBZT BHP

4VSF ZPV NBZ OBUVSBMMZ UIJOL PG UIF EBZT PG XFFL BT CFJOH OVNCFSFE  #VU
QSPHSBNNFST MJLF UP JOEFY UIJOHT GSPN [FSP
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> mod (3 - 12) 7


5
Prelude> rem (3 - 12) 7
-2

5IF WFSTJPO XJUI mod HJWFT VT B DPSSFDU BOTXFS XIJMF UIF rem
WFSTJPO EPFT OPU
0OF LFZ EJƵFSFODF IFSF JT UIBU JO )BTLFMM OPU JO BMM MBO
HVBHFT
JG POF PS CPUI BSHVNFOUT BSF OFHBUJWF UIF SFTVMUT PG
mod XJMM IBWF UIF TBNF TJHO BT UIF EJWJTPS XIJMF UIF SFTVMU PG
rem XJMM IBWF UIF TBNF TJHO BT UIF EJWJEFOE

Prelude> (-5) `mod` 2


1
Prelude> 5 `mod` (-2)
-1
Prelude> (-5) `mod` (-2)
-1

-- but

Prelude> (-5) `rem` 2


-1
Prelude> 5 `rem` (-2)
1
Prelude> (-5) `rem` (-2)
-1
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

'JHVSJOH PVU XIFO ZPV OFFE mod UBLFT TPNF FYQFSJFODF BOE
JU NBZ OPU CF PCWJPVT SJHIU OPX #VU ZPV XJMM OFFE JU MBUFS JO
UIF CPPL

/FHBUJWF OVNCFST
%VF UP UIF JOUFSBDUJPO PG QBSFOUIFTFT DVSSZJOH BOE JOƶY TZO
UBY OFHBUJWF OVNCFST HFU TQFDJBM USFBUNFOU JO )BTLFMM
*G ZPV XBOU B WBMVF UIBU JT B OFHBUJWF OVNCFS CZ JUTFMG UIJT
XJMM XPSL KVTU ƶOF

Prelude> -1000
-1000

)PXFWFS UIJT XJMM OPU XPSL JO TPNF DBTFT

Prelude> 1000 + -9
<interactive>:3:1:
Precedence parsing error
cannot mix ‘+’ [infixl 6] and
prefix `-` [infixl 6]
in the same infix expression

'PSUVOBUFMZ XF XFSF UPME BCPVU PVS NJTUBLF CFGPSF BOZ


PG PVS DPEF XBT FYFDVUFE /PUF IPX UIF FSSPS NFTTBHF UFMMT
ZPV UIF QSPCMFN IBT UP EP XJUI QSFDFEFODF "EEJUJPO BOE
TVCUSBDUJPO IBWF UIF TBNF QSFDFEFODF 
BOE ()$J UIJOLT
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

XF BSF USZJOH UP BEE BOE TVCUSBDU OPU BEE B OFHBUJWF OVNCFS


TP JU EPFTOƊU LOPX IPX UP SFTPMWF UIF QSFDFEFODF BOE FWBMVBUF
UIF FYQSFTTJPO 8F OFFE UP NBLF B TNBMM DIBOHF CFGPSF XF
DBO BEE B QPTJUJWF BOE B OFHBUJWF OVNCFS UPHFUIFS

Prelude> 1000 + (-9)


991

5IF OFHBUJPO PG OVNCFST JO )BTLFMM CZ UIF VTF PG B VOBSZ -


JT B GPSN PG TZOUBDUJD TVHBS 4ZOUBY JT UIF HSBNNBS BOE TUSVD
UVSF PG UIF UFYU XF VTF UP FYQSFTT QSPHSBNT BOE TZOUBDUJD
TVHBS JT B NFBOT GPS VT UP NBLF UIBU UFYU FBTJFS UP SFBE BOE
XSJUF 4ZOUBDUJD TVHBS DBO NBLF UIF UZQJOH PS SFBEJOH PG DPEF
OJDFS CVU DIBOHFT OPUIJOH BCPVU UIF TFNBOUJDT PS NFBOJOH PG
QSPHSBNT BOE EPFTOƊU DIBOHF IPX XF TPMWF QSPCMFNT JO DPEF
5ZQJDBMMZ XIFO DPEF XJUI TZOUBDUJD TVHBS JT QSPDFTTFE CZ PVS
3&1- PS DPNQJMFS B TJNQMF USBOTGPSNBUJPO GSPN UIF TIPSUFS
ƌTXFFUFSƍ
GPSN UP B NPSF WFSCPTF USVFS SFQSFTFOUBUJPO JT
QFSGPSNFE BǒFS UIF DPEF IBT CFFO QBSTFE
*O UIF TQFDJƶD DBTF PG - UIF TZOUBDUJD TVHBS NFBOT UIF PQFS
BUPS OPX IBT UXP QPTTJCMF JOUFSQSFUBUJPOT 5IF UXP QPTTJCMF
JOUFSQSFUBUJPOT PG UIF TZOUBDUJD - BSF UIBU - JT CFJOH VTFE BT BO
BMJBT GPS negate PS UIBU JU JT UIF TVCUSBDUJPO GVODUJPO 5IF GPM
MPXJOH BSF TFNBOUJDBMMZ JEFOUJDBM UIBU JT UIFZ IBWF UIF TBNF
NFBOJOH EFTQJUF EJƵFSFOU TZOUBY
CFDBVTF UIF - JT USBOTMBUFE
JOUP negate
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> 2000 + (-1234)


766

Prelude> 2000 + (negate 1234)


766

8IFSFBT UIJT JT - CFJOH VTFE GPS TVCUSBDUJPO

Prelude> 2000 - 1234


766

'PSUVOBUFMZ TZOUBDUJD PWFSMPBEJOH MJLF UIJT JTOƊU DPNNPO


JO )BTLFMM

 1BSFOUIFTJ[BUJPO
)FSF XFƊWF MJTUFE UIF JOGPSNBUJPO UIBU ()$J HJWFT VT GPS WBS
JPVT JOƶY PQFSBUPST 8F IBWF MFǒ UIF UZQF TJHOBUVSFT JO UIJT
UJNF BMUIPVHI JU JT OPU EJSFDUMZ SFMFWBOU BU UIJT UJNF 5IJT XJMM
HJWF ZPV B DIBODF UP MPPL BU UIF UZQFT JG ZPVƊSF DVSJPVT BOE
BMTP QSPWJEF B NPSF BDDVSBUF QJDUVSF PG UIF :info DPNNBOE

Prelude> :info (^)


(^) :: (Num a, Integral b) => a -> b -> a
infixr 8 ^

Prelude> :info (*)


$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

class Num a where


(*) :: a -> a -> a
infixl 7 *

Prelude> :info (+)


class Num a where
(+) :: a -> a -> a
infixl 6 +

Prelude> :info (-)


class Num a where
(-) :: a -> a -> a
infixl 6 -

Prelude> :info ($)


($) :: (a -> b) -> a -> b
infixr 0 $

8F TIPVME UBLF B NPNFOU UP FYQMBJO BOE EFNPOTUSBUF UIF


($) PQFSBUPS BT ZPV XJMM SVO JOUP JU GBJSMZ GSFRVFOUMZ JO )BTLFMM
DPEF 5IF HPPE OFXT JT JU EPFT BMNPTU OPUIJOH 5IF CBE OFXT
JT UIJT GBDU TPNFUJNFT USJQT QFPQMF VQ
'JSTU IFSFƊT UIF EFƶOJUJPO PG ($)

f $ a = f a
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

*NNFEJBUFMZ UIJT TFFNT B CJU QPJOUMFTT VOUJM XF SFNFNCFS


UIBU JUƊT EFƶOFE BT BO JOƶY PQFSBUPS XJUI UIF MPXFTU QPTTJCMF
QSFDFEFODF 5IF ($) PQFSBUPS JT B DPOWFOJFODF GPS XIFO ZPV
XBOU UP FYQSFTT TPNFUIJOH XJUI GFXFS QBJST PG QBSFOUIFTFT

Prelude> (2^) (2 + 2)
16
-- can replace those parentheses
Prelude> (2^) $ 2 + 2
16
-- without either parentheses or $
Prelude> (2^) 2 + 2
6

5IF ($) XJMM BMMPX FWFSZUIJOH UP UIF SJHIU PG JU UP CF FWBMV


BUFE ƶSTU BOE DBO CF VTFE UP EFMBZ GVODUJPO BQQMJDBUJPO :PVƊMM
TFF XIBU XF NFBO BCPVU EFMBZJOH GVODUJPO BQQMJDBUJPO JO QBS
UJDVMBS XIFO XF HFU UP $IBQUFS  BOE VTF JU XJUI GVODUJPO
DPNQPTJUJPO
"MTP OPUF UIBU ZPV DBO TUBDL VQ NVMUJQMF VTFT PG ($) JO UIF
TBNF FYQSFTTJPO 'PS FYBNQMF UIJT XPSLT

Prelude> (2^) $ (+2) $ 3*2


256

#VU UIJT EPFT OPU


$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> (2^) $ 2 + 2 $ (*30)


-- A rather long and ugly type error about trying to
-- use numbers as if they were functions follows.

8F DBO TFF GPS PVSTFMWFT XIZ UIJT DPEF EPFTOƊU NBLF TFOTF
JG XF FYBNJOF UIF SFEVDUJPO TUFQT

-- Remember ($)'s definition


f $ a = f a

(2^) $ 2 + 2 $ (*30)
-- Given the right-associativity (infixr) of $
-- we must begin at the right-most position.
2 + 2 $ (*30)
-- reduce ($)
(2 + 2) (*30)
-- then we must evaluate (2 + 2) before we can apply it
4 (*30)
-- This doesn't make sense! We can't apply 4
-- as if it was a function to the argument (*30)!

/PX MFUƊT ƷJQ UIBU FYQSFTTJPO BSPVOE B CJU TP JU XPSLT BOE


UIFO XBML UISPVHI B SFEVDUJPO
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

(2^) $ (*30) $ 2 + 2
-- must evaluate right-side first
(2^) $ (*30) $ 2 + 2
-- application of the function (*30) to the
-- expression (2 + 2) forces evaluation
(2^) $ (*30) 4
-- then we reduce (*30) 4
(2^) $ 120
-- reduce ($) again.
(2^) 120
-- reduce (2^)
1329227995784915872903807060280344576

4PNF )BTLFMMFST ƶOE QBSFOUIFTFT NPSF SFBEBCMF UIBO UIF


EPMMBS TJHO CVU JUƊT UPP DPNNPO JO JEJPNBUJD )BTLFMM DPEF GPS
ZPV UP OPU BU MFBTU CF GBNJMJBS XJUI JU

1BSFOUIFTJ[JOH JOƶY PQFSBUPST


5IFSF BSF UJNFT XIFO ZPV XBOU UP SFGFS UP BO JOƶY GVODUJPO
XJUIPVU BQQMZJOH BOZ BSHVNFOUT BOE UIFSF BSF BMTP UJNFT
XIFO ZPV XBOU UP VTF UIFN BT QSFƶY PQFSBUPST JOTUFBE PG JOƶY
*O CPUI DBTFT ZPV NVTU XSBQ UIF PQFSBUPS JO QBSFOUIFTFT 8F
XJMM TFF NPSF FYBNQMFT PG UIF GPSNFS DBTF MBUFS JO UIF CPPL
'PS OPX MFUƊT MPPL BU IPX XF VTF JOƶY PQFSBUPST BT QSFƶYFT
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

*G ZPVS JOƶY GVODUJPO JT >> UIFO ZPV NVTU XSJUF (>>) UP SFGFS
UP JU BT B WBMVF (+) JT UIF BEEJUJPO JOƶY GVODUJPO XJUIPVU BOZ
BSHVNFOUT BQQMJFE ZFU BOE (+1) JT UIF TBNF BEEJUJPO GVODUJPO
CVU XJUI POF BSHVNFOU BQQMJFE NBLJOH JU SFUVSO UIF OFYU
BSHVNFOU JUƊT BQQMJFE UP QMVT POF

Prelude> 1 + 2
3
Prelude> (+) 1 2
3
Prelude> (+1) 2
3

5IF MBTU DBTF JT LOPXO BT TFDUJPOJOH BOE BMMPXT ZPV UP QBTT


BSPVOE QBSUJBMMZ BQQMJFE GVODUJPOT 8JUI DPNNVUBUJWF GVOD
UJPOT TVDI BT BEEJUJPO JU NBLFT OP EJƵFSFODF JG ZPV VTF (+1)
PS (1+) CFDBVTF UIF PSEFS PG UIF BSHVNFOUT XPOƊU DIBOHF UIF
SFTVMU
*G ZPV VTF TFDUJPOJOH XJUI B GVODUJPO UIBU JT OPU DPNNVUB
UJWF UIF PSEFS NBUUFST

Prelude> (1/) 2
0.5
Prelude> (/1) 2
2.0

4VCUSBDUJPO (-) JT B TQFDJBM DBTF 5IFTF XJMM XPSL


$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> 2 - 1
1
Prelude> (-) 2 1
1

5IF GPMMPXJOH IPXFWFS XPOƊU XPSL

Prelude> (-2) 1

&ODMPTJOH B WBMVF JOTJEF UIF QBSFOUIFTFT XJUI UIF - JOEJ


DBUFT UP ()$J UIBU JUƊT UIF BSHVNFOU PG B GVODUJPO #FDBVTF
UIF - GVODUJPO SFQSFTFOUT OFHBUJPO OPU TVCUSBDUJPO XIFO JUƊT
BQQMJFE UP B TJOHMF BSHVNFOU ()$J EPFT OPU LOPX XIBU UP EP
XJUI UIBU BOE TP JU SFUVSOT BO FSSPS NFTTBHF )FSF - JT B DBTF
PG TZOUBDUJD PWFSMPBEJOH EJTBNCJHVBUFE CZ IPX JU JT VTFE
:PV DBO VTF TFDUJPOJOH GPS TVCUSBDUJPO CVU JU NVTU CF UIF
ƶSTU BSHVNFOU

Prelude> let x = 5
Prelude> let y = (1 -)
Prelude> y x
-4

0S ZPV JOTUFBE PG  Y
ZPV DBO XSJUF TVCUSBDU Y


Prelude> (subtract 2) 3
1
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

*U NBZ OPU CF JNNFEJBUFMZ PCWJPVT XIZ ZPV XPVME FWFS


XBOU UP EP UIJT CVU ZPV XJMM TFF UIJT TZOUBY VTFE UISPVHIPVU UIF
CPPL GPS FYBNQMF PODF XF TUBSU XBOUJOH UP BQQMZ GVODUJPOT UP
FBDI WBMVF JOTJEF B MJTU PS PUIFS EBUB TUSVDUVSF 8F XJMM EJTDVTT
QBSUJBM BQQMJDBUJPO PG GVODUJPOT JO NPSF EFUBJM JO B MBUFS DIBQUFS
BT XFMM

 -FU BOE XIFSF


:PV XJMM PǒFO TFF let BOE where VTFE UP JOUSPEVDF DPNQPOFOUT
PG FYQSFTTJPOT BOE UIFZ TFFN TJNJMBS *U UBLFT TPNF QSBDUJDF
UP HFU VTFE UP UIF BQQSPQSJBUF UJNFT UP VTF FBDI CVU UIFZ BSF
GVOEBNFOUBMMZ EJƵFSFOU
5IF DPOUSBTU IFSF JT UIBU let JOUSPEVDFT BO FYQSFTTJPO TP JU
DBO CF VTFE XIFSFWFS ZPV DBO IBWF BO FYQSFTTJPO CVU where JT
B EFDMBSBUJPO BOE JT CPVOE UP B TVSSPVOEJOH TZOUBDUJD DPOTUSVDU
8FƊMM TUBSU XJUI BO FYBNQMF PG where

-- FunctionWithWhere.hs
module FunctionWithWhere where

printInc n = print plusTwo


where plusTwo = n + 2

"OE JG XF VTF UIJT JO UIF 3&1-

Prelude> :l FunctionWithWhere.hs
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

[1 of 1] Compiling FunctionWithWhere ...


Ok, modules loaded: FunctionWithWhere.
Prelude> printInc 1
3
Prelude>

/PX XF IBWF UIF TBNF GVODUJPO CVU VTJOH let JO UIF QMBDF
PG where

-- FunctionWithLet.hs
module FunctionWithLet where

printInc2 n = let plusTwo = n + 2


in print plusTwo

8IFO ZPV TFF let GPMMPXFE CZ in ZPVƊSF MPPLJOH BU B MFU


FYQSFTTJPO )FSFƊT UIBU GVODUJPO JO UIF 3&1-

Prelude> :load FunctionWithLet.hs


[1 of 1] Compiling FunctionWithLet ...
Ok, modules loaded: FunctionWithLet.
Prelude> printInc2 3
5

*G ZPV MPBEFE FunctionWithLet JO UIF TBNF 3&1- TFTTJPO BT


FunctionWithWhere UIFO JU XJMM IBWF VOMPBEFE UIF ƶSTU POF CF
GPSF MPBEJOH UIF OFX POF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

Prelude> :load FunctionWithWhere.hs


[1 of 1] Compiling FunctionWithWhere ...
Ok, modules loaded: FunctionWithWhere.
Prelude> printInc 1
3
Prelude> :load FunctionWithLet.hs
[1 of 1] Compiling FunctionWithLet ...
Ok, modules loaded: FunctionWithLet.
Prelude> printInc2 10
12
Prelude> printInc 10

<interactive>:6:1:
Not in scope: ‘printInc’
Perhaps you meant ‘printInc2’ (line 4)

printInc JTOƊU JO TDPQF BOZNPSF CFDBVTF ()$J VOMPBEFE


FWFSZUIJOH ZPVƊE EFƶOFE PS MPBEFE BǒFS ZPV VTFE :load UP
MPBE UIF FunctionWithLet.hs TPVSDF ƶMF 4DPQF JT UIF BSFB PG
TPVSDF DPEF XIFSF B CJOEJOH PG B WBSJBCMF BQQMJFT
5IBU JT POF MJNJUBUJPO PG UIF :load DPNNBOE JO ()$J "T
XF CVJME MBSHFS QSPKFDUT UIBU SFRVJSF IBWJOH NVMUJQMF NPEVMFT
JO TDPQF XF XJMM VTF B QSPKFDU NBOBHFS DBMMFE 4UBDL SBUIFS
UIBO ()$J JUTFMG
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

&YFSDJTFT " )FBE $PEF


/PX GPS TPNF FYFSDJTFT 'JSTU EFUFSNJOF JO ZPVS IFBE XIBU
UIF GPMMPXJOH FYQSFTTJPOT XJMM SFUVSO UIFO WBMJEBUF JO UIF
3&1-

 let x = 5 in x

 let x = 5 in x * x

 let x = 5; y = 6 in x * y

 let x = 3; y = 1000 in x + 3

"CPWF ZPV FOUFSFE TPNF let FYQSFTTJPOT JOUP ZPVS 3&1-


UP FWBMVBUF UIFN /PX XFƊSF HPJOH UP PQFO B ƶMF BOE SFXSJUF
TPNF let FYQSFTTJPOT VTJOH where EFDMBSBUJPOT :PV XJMM IBWF
UP HJWF UIF WBMVF ZPVƊSF CJOEJOH B OBNF BMUIPVHI UIF OBNF
DBO CF KVTU B MFUUFS JG ZPV MJLF 'PS FYBNQMF

-- this should work in GHCi


let x = 5; y = 6 in x * y

DPVME CF SFXSJUUFO BT

-- put this in a file


mult1 = x * y
where x = 5
y = 6
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

.BLJOH UIF FRVBMT TJHOT MJOF VQ JT B TUZMJTUJD DIPJDF "T MPOH


BT UIJOHT BSF OFTUFE JO UIBU XBZ UIF FRVBMT TJHOT EP OPU IBWF
UP MJOF VQ #VU OPUJDF XF VTF B OBNF UIBU XF XJMM VTF UP SFGFS
UP UIJT WBMVF JO UIF 3&1-

Prelude> :l practice.hs
[1 of 1] Compiling Main
Ok, modules loaded: Main.
*Main> mult1
30

5IF QSPNQU DIBOHFT UP *Main JOTUFBE PG Prelude UP JOEJDBUF


UIBU ZPV IBWF B NPEVMF DBMMFE Main MPBEFE
3FXSJUF XJUI where DMBVTFT

 let x = 3; y = 1000 in x * 3 + y

 let y = 10; x = 10 * 5 + y in x * 5

 let x = 7; y = negate x; z = y * 10 in z / x + y

/PUF UIF ƶMFOBNF ZPV DIPPTF JT VOJNQPSUBOU FYDFQU GPS


UIF IT FYUFOTJPO

 $IBQUFS &YFSDJTFT


5IF HPBM GPS BMM UIF GPMMPXJOH FYFSDJTFT JT KVTU UP HFU ZPV QMBZ
JOH XJUI DPEF BOE GPSNJOH IZQPUIFTFT BCPVU XIBU JU TIPVME
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

EP 3FBE UIF DPEF DBSFGVMMZ VTJOH XIBU XFƊWF MFBSOFE TP GBS
(FOFSBUF B IZQPUIFTJT BCPVU XIBU ZPV UIJOL UIF DPEF XJMM EP
1MBZ XJUI JU JO UIF 3&1- BOE ƶOE PVU XIFSF ZPV XFSF SJHIU PS
XSPOH

1BSFOUIFTJ[BUJPO
(JWFO XIBU XF LOPX BCPVU UIF QSFDFEFODF PG (*) (+) BOE (^)
IPX DBO XF QBSFOUIFTJ[F UIF GPMMPXJOH FYQSFTTJPOT NPSF FY
QMJDJUMZ XJUIPVU DIBOHJOH UIFJS SFTVMUT 1VU UPHFUIFS BO BOTXFS
ZPV UIJOL JT DPSSFDU UIFO UFTU JO UIF ()$J 3&1-
&YBNQMF

-- We want to make this more explicit


2 + 2 * 3 - 3

-- this will produce the same result


2 + (2 * 3) - 3

"UUFNQU UIF BCPWF PO UIF GPMMPXJOH FYQSFTTJPOT

 2 + 2 * 3 - 1

 (^) 10 $ 1 + 1

 2 ^ 2 * 4 ^ 5 + 1
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

&RVJWBMFOU FYQSFTTJPOT
8IJDI PG UIF GPMMPXJOH QBJST PG FYQSFTTJPOT XJMM SFUVSO UIF
TBNF SFTVMU XIFO FWBMVBUFE 5SZ UP SFBTPO UIFN PVU JO ZPVS
IFBE CZ SFBEJOH UIF DPEF BOE UIFO FOUFS UIFN JOUP UIF 3&1-
UP DIFDL ZPVS XPSL

 1 + 1

 10 ^ 2

10 + 9 * 10

 400 - 37

(-) 37 400

 100 `div` 3

100 / 3

 2 * 5 + 18

2 * (5 + 18)
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

.PSF GVO XJUI GVODUJPOT


)FSF JT B CJU PG DPEF BT JU NJHIU CF FOUFSFE JOUP B TPVSDF ƶMF
3FNFNCFS UIBU XIFO ZPV XSJUF DPEF JO B TPVSDF ƶMF UIF PSEFS
JT VOJNQPSUBOU CVU XIFO XSJUJOH DPEF EJSFDUMZ JOUP UIF 3&1-
UIF PSEFS EPFT NBUUFS (JWFO UIBU MPPL BU UIJT DPEF BOE SFXSJUF
JU TVDI UIBU JU DPVME CF FWBMVBUFE JO UIF 3&1- SFNFNCFS
ZPVƊMM OFFE let XIFO FOUFSJOH JU EJSFDUMZ JOUP UIF 3&1-
 #F
TVSF UP FOUFS ZPVS DPEF JOUP UIF 3&1- UP NBLF TVSF JU FWBMVBUFT
DPSSFDUMZ

z = 7

x = y ^ 2

waxOn = x * 5

y = z + 8

 /PX ZPV IBWF B WBMVF DBMMFE waxOn JO ZPVS 3&1- 8IBU EP


ZPV UIJOL XJMM IBQQFO JG ZPV FOUFS
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

10 + waxOn
-- or
(+10) waxOn
-- or
(-) 15 waxOn
-- or
(-) waxOn 15

 &BSMJFS XF MPPLFE BU B GVODUJPO DBMMFE triple 8IJMF ZPVS


3&1- IBT waxOn JO TFTTJPO SFFOUFS UIF triple GVODUJPO BU
UIF QSPNQU

let triple x = x * 3

 /PX XIBU XJMM IBQQFO JG XF FOUFS UIJT BU PVS ()$J QSPNQU


5SZ UP SFBTPO PVU XIBU ZPV UIJOL XJMM IBQQFO ƶSTU DPOTJE
FSJOH XIBU SPMF waxOn JT QMBZJOH JO UIJT GVODUJPO DBMM 5IFO
FOUFS JU TFF XIBU EPFT IBQQFO BOE DIFDL ZPVS VOEFS
TUBOEJOH

triple waxOn

 3FXSJUF waxOn BT BO FYQSFTTJPO XJUI B where DMBVTF JO ZPVS


TPVSDF ƶMF -PBE JU JOUP ZPVS 3&1- BOE NBLF TVSF JU TUJMM
XPSLT BT FYQFDUFE

 /PX UP UIF TBNF TPVSDF ƶMF XIFSF ZPV IBWF waxOn BEE
UIF triple GVODUJPO 3FNFNCFS :PV EPOƊU OFFE let BOE
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

UIF GVODUJPO OBNF TIPVME CF BU UIF MFǒ NBSHJO UIBU JT


OPU OFTUFE BT POF PG UIF waxOn FYQSFTTJPOT
 .BLF TVSF
JU XPSLT CZ MPBEJOH JU JOUP ZPVS 3&1- BOE UIFO FOUFSJOH
triple waxOn BHBJO BU UIF 3&1- QSPNQU :PV TIPVME IBWF
UIF TBNF BOTXFS BT ZPV EJE BCPWF

 /PX XJUIPVU DIBOHJOH XIBU ZPVƊWF EPOF TP GBS JO UIBU


ƶMF BEE B OFX GVODUJPO DBMMFE waxOff UIBU MPPLT MJLF UIJT

waxOff x = triple x

 -PBE UIF TPVSDF ƶMF JOUP ZPVS 3&1- BOE FOUFS waxOff waxOn
BU UIF QSPNQU
:PV OPX IBWF B GVODUJPO waxOff UIBU DBO CF BQQMJFE UP B
WBSJFUZ PG BSHVNFOUT ƈ OPU KVTU waxOn CVU BOZ OVNFSJD

WBMVF ZPV XBOU UP QVU JO GPS ԧ 1MBZ XJUI UIBU B CJU 8IBU
JT UIF SFTVMU PG waxOff 10 PS waxOff (-50) 5SZ NPEJGZJOH
ZPVS waxOff GVODUJPO UP EP TPNFUIJOH OFX ƈ QFSIBQT ZPV
XBOU UP ƶSTU USJQMF UIF ԧ WBMVF BOE UIFO TRVBSF JU PS EJWJEF
JU CZ  +VTU TQFOE TPNF UJNF HFUUJOH DPNGPSUBCMF XJUI
NPEJGZJOH UIF TPVSDF ƶMF DPEF SFMPBEJOH JU BOE DIFDLJOH
ZPVS NPEJƶDBUJPO JO UIF 3&1-

 %FƶOJUJPOT
 5IF UFSNT BSHVNFOU BOE QBSBNFUFS BSF PǒFO VTFE JOUFS
DIBOHFBCMZ )PXFWFS JU JT XPSUIXIJMF UP VOEFSTUBOE UIF
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

EJTUJODUJPO " QBSBNFUFS PS GPSNBM QBSBNFUFS SFQSFTFOUT B


WBMVF UIBU XJMM CF QBTTFE UP UIF GVODUJPO XIFO UIF GVOD
UJPO JT DBMMFE 5IVT QBSBNFUFST BSF VTVBMMZ WBSJBCMFT "O
BSHVNFOU JT BO JOQVU WBMVF UIF GVODUJPO JT BQQMJFE UP "
GVODUJPOƊT QBSBNFUFS JT CPVOE UP UIF WBMVF PG BO BSHVNFOU
XIFO UIF GVODUJPO JT BQQMJFE UP UIBU BSHVNFOU 'PS FYBN
QMF JO f x = x + 2 XIJDI UBLFT BO BSHVNFOU BOE SFUVSOT
UIBU WBMVF BEEFE UP  ԧ JT UIF POF QBSBNFUFS PG PVS GVOD
UJPO 8F SVO UIF DPEF CZ BQQMZJOH ԕ UP TPNF BSHVNFOU
*G UIF BSHVNFOU XF QBTTFE UP UIF QBSBNFUFS ԧ XFSF  PVS
SFTVMU XPVME CF  )PXFWFS BSHVNFOUT DBO UIFNTFMWFT
CF WBSJBCMFT PS CF FYQSFTTJPOT UIBU JODMVEF WBSJBCMFT UIVT
UIF EJTUJODUJPO JT OPU BMXBZT DMFBS 8IFO XF VTF ƌQBSBN
FUFSƍ JO UIJT CPPL JU XJMM BMXBZT CF SFGFSSJOH UP GPSNBM
QBSBNFUFST VTVBMMZ JO B UZQF TJHOBUVSF CVU XFƊWF UBLFO
UIF MJCFSUZ PG VTJOH ƌBSHVNFOUƍ TPNFXIBU NPSF MPPTFMZ

 "O FYQSFTTJPO JT B DPNCJOBUJPO PG TZNCPMT UIBU DPOGPSNT


UP TZOUBDUJD SVMFT BOE DBO CF FWBMVBUFE UP TPNF SFTVMU *O
)BTLFMM BO FYQSFTTJPO JT B XFMMTUSVDUVSFE DPNCJOBUJPO
PG DPOTUBOUT WBSJBCMFT BOE GVODUJPOT 8IJMF JSSFEVDJCMF
DPOTUBOUT BSF UFDIOJDBMMZ FYQSFTTJPOT XF VTVBMMZ SFGFS UP
UIPTF BT ƌWBMVFTƍ TP XF VTVBMMZ NFBO ƌSFEVDJCMF FYQSFT
TJPOƍ XIFO XF VTF UIF UFSN FYQSFTTJPO

 " SFEFY JT B SFEVDJCMF FYQSFTTJPO


$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

 " WBMVF JT BO FYQSFTTJPO UIBU DBOOPU CF SFEVDFE PS FWBMV


BUFE BOZ GVSUIFS 2 * 2 JT BO FYQSFTTJPO CVU OPU B WBMVF
XIFSFBT XIBU JU FWBMVBUFT UP  JT B WBMVF

 " GVODUJPO JT B NBUIFNBUJDBM PCKFDU XIPTF DBQBCJMJUJFT BSF


MJNJUFE UP CFJOH BQQMJFE UP BO BSHVNFOU BOE SFUVSOJOH B
SFTVMU 'VODUJPOT DBO CF EFTDSJCFE BT B MJTU PG PSEFSFE QBJST
PG UIFJS JOQVUT BOE UIF SFTVMUJOH PVUQVUT MJLF B NBQQJOH
(JWFO UIF GVODUJPO f x = x + 2 BQQMJFE UP UIF BSHVNFOU
 XF XPVME IBWF UIF PSEFSFE QBJS (2, 4) PG JUT JOQVU BOE
PVUQVU

 *OƶY OPUBUJPO JT UIF TUZMF VTFE JO BSJUINFUJD BOE MPHJD *OƶY


NFBOT UIBU UIF PQFSBUPS JT QMBDFE CFUXFFO UIF PQFSBOET
PS BSHVNFOUT "O FYBNQMF XPVME CF UIF QMVT TJHO JO BO
FYQSFTTJPO MJLF 2 + 2

 0QFSBUPST BSF GVODUJPOT UIBU BSF JOƶY CZ EFGBVMU *O )BTLFMM


PQFSBUPST NVTU VTF TZNCPMT BOE OPU BMQIBOVNFSJD DIBS
BDUFST

 4ZOUBDUJD TVHBS JT TZOUBY XJUIJO B QSPHSBNNJOH MBOHVBHF


EFTJHOFE UP NBLF FYQSFTTJPOT FBTJFS UP XSJUF PS SFBE

 'PMMPXVQ SFTPVSDFT


 )BTLFMM XJLJ BSUJDMF PO -FU WT 8IFSF
https://wiki.haskell.org/Let_vs._Where
$)"15&3  #"4*$ &913&44*0/4 "/% '6/$5*0/4 

 )PX UP EFTVHBS )BTLFMM DPEF (BCSJFM (PO[BMF[


$IBQUFS 

4USJOHT

-JLF QVOOJOH
QSPHSBNNJOH JT B QMBZ PO
XPSET

"MBO 1FSMJT


$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

 1SJOUJOH TUSJOHT


4P GBS XFƊWF CFFO EPJOH BSJUINFUJD VTJOH TJNQMF FYQSFTTJPOT
*O UIJT DIBQUFS XF XJMM UVSO PVS BUUFOUJPO UP B EJƵFSFOU UZQF
PG EBUB DBMMFE String
.PTU QSPHSBNNJOH MBOHVBHFT SFGFS UP UIF EBUB TUSVDUVSFT
VTFE UP DPOUBJO UFYU BT ƌTUSJOHT ƍ VTVBMMZ SFQSFTFOUFE BT TF
RVFODFT PS MJTUT PG DIBSBDUFST *O UIJT TFDUJPO XF XJMM

Ƒ UBLF BO JOUSPEVDUPSZ MPPL BU UZQFT UP VOEFSTUBOE UIF EBUB


TUSVDUVSF DBMMFE 4USJOH

Ƒ UBML BCPVU UIF TQFDJBM TZOUBY PS TZOUBDUJD TVHBS VTFE GPS


TUSJOHT

Ƒ QSJOU TUSJOHT JO UIF 3&1- FOWJSPONFOU

Ƒ XPSL XJUI TPNF TUBOEBSE GVODUJPOT UIBU PQFSBUF PO UIJT


EBUBUZQF

 " ƶSTU MPPL BU UZQFT


'JSTU TJODF XF XJMM CF XPSLJOH XJUI TUSJOHT XF XBOU UP TUBSU CZ
VOEFSTUBOEJOH XIBU UIFTF EBUB TUSVDUVSFT BSF JO )BTLFMM BT XFMM
BT B CJU PG TQFDJBM TZOUBY XF VTF GPS UIFN 8F IBWFOƊU UBMLFE
NVDI BCPVU UZQFT ZFU BMUIPVHI ZPV TBX TPNF FYBNQMFT PG
UIFN JO UIF MBTU DIBQUFS 5ZQFT BSF JNQPSUBOU JO )BTLFMM BOE
UIF OFYU UXP DIBQUFST BSF FOUJSFMZ EFWPUFE UP UIFN
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

5ZQFT BSF B XBZ PG DBUFHPSJ[JOH WBMVFT 5IFSF BSF TFW


FSBM UZQFT GPS OVNCFST GPS FYBNQMF EFQFOEJOH PO XIFUIFS
UIFZ BSF JOUFHFST GSBDUJPOBM OVNCFST FUD 5IFSF JT B UZQF
GPS CPPMFBO WBMVFT TQFDJƶDBMMZ UIF WBMVFT True BOE False 5IF
UZQFT XF BSF QSJNBSJMZ DPODFSOFE XJUI JO UIJT DIBQUFS BSF Char
ƉDIBSBDUFSƊ BOE String StringT BSF MJTUT PG DIBSBDUFST
*U JT FBTZ UP ƶOE PVU UIF UZQF PG B WBMVF FYQSFTTJPO PS
GVODUJPO JO ()$J 8F EP UIJT XJUI UIF :type DPNNBOE
0QFO VQ ZPVS 3&1- FOUFS :type 'a' BU UIF QSPNQU BOE
ZPV TIPVME TFF TPNFUIJOH MJLF UIJT

Prelude> :type 'a'


'a' :: Char

8F OFFE UP IJHIMJHIU B GFX UIJOHT IFSF 'JSTU XFƊWF FODMPTFE


PVS DIBSBDUFS JO TJOHMF RVPUFT 5IJT MFUT ()$J LOPX UIBU UIF
DIBSBDUFS JT OPU B WBSJBCMF *G ZPV FOUFS :type a JOTUFBE JU XJMM
UIJOL JUƊT B WBSJBCMF BOE HJWF ZPV BO FSSPS NFTTBHF UIBU UIF Ԑ JT
OPU JO TDPQF 5IBU JT UIF WBSJBCMF Ԑ IBTOƊU CFFO EFƶOFE JT OPU
JO TDPQF
TP JU IBT OP XBZ UP LOPX XIBU UIF UZQF PG JU JT
4FDPOE UIF :: TZNCPM JT SFBE BT ƌIBT UIF UZQFƍ :PVƊMM TFF
UIJT PǒFO JO )BTLFMM 8IFOFWFS ZPV TFF UIBU EPVCMF DPMPO
ZPV LOPX ZPVƊSF MPPLJOH BU B UZQF TJHOBUVSF " UZQF TJHOBUVSF
JT B MJOF PG DPEF UIBU EFƶOFT UIF UZQFT GPS B WBMVF FYQSFTTJPO
PS GVODUJPO
"OE ƶOBMMZ UIFSF JT Char UIF UZQF Char JT UIF UZQF UIBU
JODMVEFT BMQIBCFUJD DIBSBDUFST VOJDPEF DIBSBDUFST TZNCPMT
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

FUD 4P BTLJOH ()$J :type 'a' UIBU JT ƌXIBU JT UIF UZQF PG ƊBƊ ƍ
HJWFT VT UIF JOGPSNBUJPO 'a' :: Char UIBU JT ƌƊBƊ IBT UIF UZQF
PG $IBSƍ
/PX MFUƊT USZ B TUSJOH PG UFYU 5IJT UJNF XF IBWF UP VTF
EPVCMF RVPUBUJPO NBSLT OPU TJOHMF UP UFMM ()$J XF IBWF B
TUSJOH OPU B TJOHMF DIBSBDUFS

Prelude> :type "Hello!"


"Hello!" :: [Char]

8F IBWF TPNFUIJOH OFX JO UIF UZQF JOGPSNBUJPO 5IF


TRVBSF CSBDLFUT BSPVOE Char IFSF BSF UIF TZOUBDUJD TVHBS GPS B
MJTU String JT B UZQF BMJBT PS UZQF TZOPOZN GPS B MJTU PG Char "
UZQF BMJBT JT XIBU JU TPVOET MJLF XF VTF POF OBNF GPS B UZQF
VTVBMMZ GPS DPOWFOJFODF UIBU IBT B EJƵFSFOU UZQF OBNF VOEFS
OFBUI )FSF String JT BOPUIFS OBNF GPS B MJTU PG DIBSBDUFST #Z
VTJOH UIF OBNF String XF BSF BCMF UP WJTVBMMZ EJƵFSFOUJBUF JU
GSPN PUIFS UZQFT PG MJTUT BOE OBNFT UIFNTFMWFT EPOƊU NFBO
NVDI UP UIF DPNQVUFS 8IFO XF UBML BCPVU MJTUT JO NPSF EFUBJM
MBUFS XFƊMM TFF XIZ UIF TRVBSF CSBDLFUT BSF DPOTJEFSFE TZOUBD
UJD TVHBS GPS OPX XF KVTU OFFE UP VOEFSTUBOE UIBU ()$J TBZT
ƌ)FMMPƍ IBT UIF UZQF MJTU PG Char

 1SJOUJOH TJNQMF TUSJOHT


/PX MFUƊT TFF IPX UP QSJOU TUSJOHT PG UFYU JO UIF 3&1-
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

Prelude> print "hello world!"


"hello world!"

)FSF XFƊWF VTFE UIF DPNNBOE print UP UFMM ()$J UP QSJOU


UIF TUSJOH UP UIF EJTQMBZ TP JU EPFT XJUI UIF RVPUBUJPO NBSLT
TUJMM BSPVOE JU
0UIFS DPNNBOET XF DBO VTF UP UFMM ()$J UP QSJOU TUSJOHT
PG UFYU JOUP UIF EJTQMBZ IBWF TMJHIUMZ EJƵFSFOU SFTVMUT

Prelude> putStrLn "hello world!"


hello world!
Prelude>

Prelude> putStr "hello world!"


hello world!Prelude>

:PV DBO QSPCBCMZ TFF UIBU putStr BOE putStrLn BSF TJNJMBS UP
FBDI PUIFS XJUI POF LFZ EJƵFSFODF 8F BMTP OPUJDF UIBU CPUI
PG UIFTF DPNNBOET QSJOU UIF TUSJOH UP UIF EJTQMBZ XJUIPVU UIF
RVPUBUJPO NBSLT 5IJT JT CFDBVTF XIJMF UIFZ BSF TVQFSƶDJBMMZ
TJNJMBS UP print UIFZ BDUVBMMZ IBWF B EJƵFSFOU UZQF UIBO print
EPFT 'VODUJPOT UIBU BSF TJNJMBS PO UIF TVSGBDF DBO CFIBWF
EJƵFSFOUMZ EFQFOEJOH PO UIF UZQF PS DBUFHPSZ UIFZ CFMPOH UP
/FYU MFUƊT UBLF B MPPL BU IPX UP EP UIFTF UIJOHT GSPN TPVSDF
ƶMFT 5ZQF UIF GPMMPXJOH JOUP B ƶMF OBNFE print1.hs
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

-- print1.hs
module Print1 where

main :: IO ()
main = putStrLn "hello world!"

)FSFƊT XIBU ZPV TIPVME TFF XIFO ZPV MPBE JU JO ()$J BOE
SVO main

Prelude> :l print1.hs
[1 of 1] Compiling Print1
Ok, modules loaded: Print1.
*Print1> main
hello world!
*Print1>

'JSTU OPUF UIBU ZPVS Prelude> QSPNQU NBZ IBWF DIBOHFE


UP SFƷFDU UIF OBNF PG UIF NPEVMF ZPV MPBEFE :PV DBO VTF
:module PS :m UP VOMPBE UIF NPEVMF BOE SFUVSO UP 1SFMVEF JG
ZPV XJTI :PV DBO BMTP TFU ZPVS QSPNQU UP TPNFUIJOH TQFDJƶD
XIJDI NFBOT JU XPOƊU DIBOHF FWFSZ UJNF ZPV MPBE PS VOMPBE B
NPEVMF 

Prelude> :set prompt "λ> "


λ> :r

:PV DBO TFU JU QFSNBOFOUMZ JG ZPV QSFGFS CZ TFUUJOH UIF DPOƶHVSBUJPO JO ZPVS HIDJ
ƶMF
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

Ok, modules loaded: Print1.


λ> main
hello world!
λ>

-PPLJOH BU UIF DPEF BHBJO main JT UIF EFGBVMU BDUJPO XIFO


ZPV CVJME BO FYFDVUBCMF PS SVO JU JO B 3&1- *U JT OPU B GVOD
UJPO CVU JT PǒFO B TFSJFT PG JOTUSVDUJPOT UP FYFDVUF XIJDI DBO
JODMVEF BQQMZJOH GVODUJPOT BOE QSPEVDJOH TJEFFƵFDUT 8IFO
CVJMEJOH B QSPKFDU XJUI 4UBDL IBWJOH B main FYFDVUBCMF JO B
Main.hs ƶMF JT PCMJHBUPSZ CVU ZPV DBO IBWF TPVSDF ƶMFT BOE MPBE
UIFN JO ()$J XJUIPVU OFDFTTBSJMZ IBWJOH B main CMPDL
"T ZPV DBO TFF main IBT UIF UZQF IO () IO TUBOET GPS JO
QVUPVUQVU CVU IBT B TQFDJBMJ[FE NFBOJOH JO )BTLFMM *U JT B
TQFDJBM UZQF VTFE XIFO UIF SFTVMU PG SVOOJOH UIF QSPHSBN JO
WPMWFT FƵFDUT JO BEEJUJPO UP CFJOH B GVODUJPO PS FYQSFTTJPO
1SJOUJOH UP UIF TDSFFO JT BO FƵFDU TP QSJOUJOH UIF PVUQVU PG
B NPEVMF NVTU CF XSBQQFE JO UIJT IO UZQF 8IFO ZPV FOUFS
GVODUJPOT EJSFDUMZ JOUP UIF 3&1- ()$J JNQMJDJUMZ VOEFSTUBOET
BOE JNQMFNFOUT IO XJUIPVU ZPV IBWJOH UP TQFDJGZ UIBU 4JODF
UIF main BDUJPO JT UIF EFGBVMU FYFDVUBCMF ZPV XJMM TFF JU JO B MPU
PG TPVSDF ƶMFT UIBU XF CVJME GSPN IFSF PO PVU 8F XJMM FYQMBJO
JUT NFBOJOH JO NPSF EFUBJM JO B MBUFS DIBQUFS
-FUƊT TUBSU BOPUIFS ƶMF
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

-- print2.hs
module Print2 where

main :: IO ()
main = do
putStrLn "Count to four for me:"
putStr "one, two"
putStr ", three, and"
putStrLn " four!"

5IJT do TZOUBY JT B TQFDJBM TZOUBY UIBU BMMPXT GPS TFRVFODJOH


BDUJPOT *U JT NPTU DPNNPOMZ VTFE UP TFRVFODF UIF BDUJPOT
UIBU DPOTUJUVUF ZPVS QSPHSBN TPNF PG XIJDI XJMM OFDFTTBSJMZ
QFSGPSN FƵFDUT TVDI BT QSJOUJOH UP UIF TDSFFO UIBUƊT XIZ UIF
PCMJHBUPSZ UZQF PG main JT IO ()
 5IF do JTOƊU TUSJDUMZ OFDFTTBSZ
CVU TJODF JU PǒFO NBLFT GPS NPSF SFBEBCMF DPEF UIBO UIF BM
UFSOBUJWFT ZPVƊMM TFF JU B MPU 8F XJMM FYQMBJO JU B CJU NPSF JO
$IBQUFS  BOE UIFSF XJMM CF B GVMM FYQMBOBUJPO JO UIF DIBQUFS
PO .POBE
)FSFƊT XIBU ZPV TIPVME TFF XIFO ZPV SVO UIJT POF

Prelude> :l print2.hs
[1 of 1] Compiling Print2
Ok, modules loaded: Print2.
Prelude> main
Count to four for me:
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

one, two, three, and four!


Prelude>

'PS B CJU PG GVO DIBOHF UIF JOWPDBUJPOT PG putStr UP putStrLn


BOE WJDF WFSTB 3FSVO UIF QSPHSBN BOE TFF XIBU IBQQFOT
:PVƊMM OPUF UIF putStrLn GVODUJPO QSJOUT UP UIF DVSSFOU MJOF
UIFO TUBSUT B OFX MJOF XIFSF putStr QSJOUT UP UIF DVSSFOU MJOF
CVU EPFTOƊU TUBSU B OFX POF 5IF Ln JO putStrLn JOEJDBUFT UIBU JU
TUBSUT B OFX MJOF

4USJOH DPODBUFOBUJPO
5P DPODBUFOBUF TPNFUIJOH NFBOT UP MJOL UPHFUIFS 6TVBMMZ XIFO
XF UBML BCPVU DPODBUFOBUJPO JO QSPHSBNNJOH XFƊSF UBMLJOH
BCPVU MJOFBS TFRVFODFT TVDI BT MJTUT PS TUSJOHT PG UFYU *G XF
DPODBUFOBUF UXP TUSJOHT "Curry" BOE " Rocks!" XF XJMM HFU UIF
TUSJOH "Curry Rocks!" /PUF UIF TQBDF BU UIF CFHJOOJOH PG "
Rocks!" 8JUIPVU UIBU XFƊE HFU "CurryRocks!"
-FUƊT TUBSU B OFX UFYU ƶMF BOE UZQF UIF GPMMPXJOH
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

-- print3.hs
module Print3 where

myGreeting :: String
-- The above line reads as: "myGreeting has the type String"
myGreeting = "hello" ++ " world!"
-- Could also be: "hello" ++ " " ++ "world!"
-- to obtain the same result.

hello :: String
hello = "hello"

world :: String
world = "world!"

main :: IO ()
main = do
putStrLn myGreeting
putStrLn secondGreeting
where secondGreeting = concat [hello, " ", world]

3FNFNCFS String JT B UZQF TZOPOZN GPS [Char] :PV DBO


USZ DIBOHJOH UIF UZQF TJHOBUVSFT UP SFƷFDU UIBU BOE TFF JG JU
DIBOHFT BOZUIJOH JO UIF QSPHSBN FYFDVUJPO
*G ZPV FYFDVUF UIJT ZPV TIPVME TFF TPNFUIJOH MJLF
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

Prelude> :load print3.hs


[1 of 1] Compiling Print3
Ok, modules loaded: Print3.
*Print3> main
hello world!
hello world!
*Print3>

5IJT MJUUMF FYFSDJTF EFNPOTUSBUFT B GFX UIJOHT

 8F EFƶOFE WBMVFT BU UIF UPQ MFWFM PG B NPEVMF myGreeting


hello world BOE main
 5IBU JT UIFZ XFSF EFDMBSFE BU UIF
UPQ MFWFM TP UIBU UIFZ BSF BWBJMBCMF UISPVHIPVU UIF NPEVMF

 8F TQFDJGZ FYQMJDJU UZQFT GPS UPQMFWFM EFƶOJUJPOT

 8F DPODBUFOBUF TUSJOHT XJUI (++) BOE concat

 5PQMFWFM WFSTVT MPDBM EFƶOJUJPOT


8IBU EPFT JU NFBO GPS TPNFUIJOH UP CF BU UIF UPQ MFWFM PG B
NPEVMF *U EPFTOƊU OFDFTTBSJMZ NFBO JUƊT EFƶOFE BU UIF UPQ PG
UIF ƶMF 8IFO UIF DPNQJMFS SFBET UIF ƶMF JU XJMM TFF BMM UIF
UPQMFWFM EFDMBSBUJPOT OP NBUUFS XIBU PSEFS UIFZ DPNF JO UIF
ƶMF XJUI TPNF MJNJUBUJPOT XIJDI XFƊMM TFF MBUFS
 5PQMFWFM
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

EFDMBSBUJPOT BSF OPU OFTUFE XJUIJO BOZUIJOH FMTF BOE UIFZ BSF
JO TDPQF UISPVHIPVU UIF XIPMF NPEVMF
8F DBO DPOUSBTU B UPQMFWFM EFƶOJUJPO XJUI B MPDBM EFƶOJUJPO
5P CF MPDBMMZ EFƶOFE XPVME NFBO UIF EFDMBSBUJPO JT OFTUFE
XJUIJO TPNF PUIFS FYQSFTTJPO BOE JT OPU WJTJCMF PVUTJEF UIBU
FYQSFTTJPO 8F QSBDUJDFE UIJT JO UIF QSFWJPVT DIBQUFS XJUI let
BOE where )FSFƊT BO FYBNQMF GPS SFWJFX

module TopOrLocal where

topLevelFunction :: Integer -> Integer


topLevelFunction x = x + woot + topLevelValue
where woot :: Integer
woot = 10

topLevelValue :: Integer
topLevelValue = 5

*O UIF BCPWF ZPV DPVME JNQPSU BOE VTF topLevelFunction


PS topLevelValue GSPN BOPUIFS NPEVMF BOE UIFZ BSF BDDFTTJ
CMF UP FWFSZUIJOH FMTF JO UIF NPEVMF )PXFWFS woot JT FƵFD
UJWFMZ JOWJTJCMF PVUTJEF PG topLevelFunction 5IF where BOE let
DMBVTFT JO )BTLFMM JOUSPEVDF MPDBM CJOEJOHT PS EFDMBSBUJPOT
5P CJOE PS EFDMBSF TPNFUIJOH NFBOT UP HJWF BO FYQSFTTJPO B
OBNF :PV DPVME QBTT BSPVOE BOE VTF BO BOPOZNPVT WFSTJPO
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

PG topLevelFunction NBOVBMMZ CVU HJWJOH JU B OBNF BOE SFVTJOH


JU CZ UIBU OBNF JT MFTT SFQFUJUJPVT
"MTP OPUF XF FYQMJDJUMZ EFDMBSFE UIF UZQF PG woot JO UIF where
DMBVTF VTJOH UIF :: TZOUBY 5IJT XBTOƊU OFDFTTBSZ )BTLFMMƊT
UZQF JOGFSFODF XPVMEƊWF ƶHVSFE JU PVU
CVU JU XBT EPOF IFSF
UP TIPX ZPV IPX #F TVSF UP MPBE BOE SVO UIJT DPEF JO ZPVS
3&1-

Prelude> :l TopOrLocal.hs
[1 of 1] Compiling TopOrLocal
Ok, modules loaded: TopOrLocal.
*TopOrLocal> topLevelFunction 5
20

&YQFSJNFOU XJUI EJƵFSFOU BSHVNFOUT BOE NBLF TVSF ZPV


VOEFSTUBOE UIF SFTVMUT ZPVƊSF HFUUJOH CZ XBMLJOH UISPVHI UIF
BSJUINFUJD JO ZPVS IFBE PS PO QBQFS


&YFSDJTFT 4DPQF
 5IFTF MJOFT PG DPEF BSF GSPN B 3&1- TFTTJPO *T Ԩ JO TDPQF
GPS ԩ

Prelude> let x = 5
Prelude> let y = 7
Prelude> let z = x * y
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

 5IFTF MJOFT PG DPEF BSF GSPN B 3&1- TFTTJPO *T ԗ JO TDPQF


GPS GVODUJPO Ԗ (P XJUI ZPVS HVU IFSF

Prelude> let f = 3
Prelude> let g = 6 * f + h

 5IJT DPEF TBNQMF JT GSPN B TPVSDF ƶMF *T FWFSZUIJOH XF


OFFE UP FYFDVUF area JO TDPQF

area d = pi * (r * r)
r = d / 2

 5IJT DPEF JT BMTP GSPN B TPVSDF ƶMF /PX BSF ԡ BOE ԓ JO


TDPQF GPS area

area d = pi * (r * r)
where r = d / 2

 5ZQFT PG DPODBUFOBUJPO GVODUJPOT


-FUƊT MPPL BU UIF UZQFT PG (++) BOE concat 5IF ++ GVODUJPO JT
BO JOƶY PQFSBUPS 8IFO XF OFFE UP SFGFS UP BO JOƶY PQFSBUPS
JO B QPTJUJPO UIBU JT OPU JOƶY ƈ TVDI BT XIFO XF BSF VTJOH JU
JO B QSFƶY QPTJUJPO PS IBWJOH JU TUBOE BMPOF JO PSEFS UP RVFSZ
JUT UZQF ƈ XF NVTU QVU QBSFOUIFTFT BSPVOE JU 0O UIF PUIFS
IBOE concat JT B OPSNBM OPU JOƶY
GVODUJPO TP QBSFOUIFTFT
BSFOƊU OFDFTTBSZ
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

++ has the type [a] -> [a] -> [a]


concat has the type [[a]] -> [a]

-- Here's how we query that in ghci:


Prelude> :t (++)
(++) :: [a] -> [a] -> [a]
Prelude> :t concat
concat :: [[a]] -> [a]

5IF UZQF PG concat TBZT UIBU XF IBWF B MJTU PG MJTUT BT JOQVU


BOE XF XJMM SFUVSO B MJTU *U XJMM IBWF UIF TBNF WBMVFT JOTJEF JU
BT UIF MJTU PG MJTUT EJE JU KVTU ƷBUUFOT JU JOUP POF MJTU TUSVDUVSF JO
B NBOOFS PG TQFBLJOH " String JT B MJTU B MJTU PG Char TQFDJƶDBMMZ
BOE concat DBO XPSL PO MJTUT PG TUSJOHT PS MJTUT PG MJTUT PG PUIFS
UIJOHT

Prelude> concat [[1, 2], [3, 4, 5], [6, 7]]


[1,2,3,4,5,6,7]
Prelude> concat ["Iowa", "Melman", "Django"]
"IowaMelmanDjango"

OC "TTVNJOH ZPV BSF VTJOH ()$  PS IJHIFS JG ZPV


DIFDL UIJT UZQF TJHOBUVSF JO ZPVS 3&1- ZPV XJMM ƶOE EJƵFSFOU
SFTVMU 8F XJMM FYQMBJO UIF SFBTPO GPS JU MBUFS JO UIF CPPL 'PS
ZPVS QVSQPTFT BU UIJT QPJOU QMFBTF VOEFSTUBOE Foldable t =>
t [a] BT CFJOH [[a]] 5IF Foldable t GPS PVS DVSSFOU QVSQPTFT
DBO CF UIPVHIU PG BT BOPUIFS MJTU *O USVUI MJTU JT POMZ POF PG UIF
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

QPTTJCMF UZQFT IFSF ƈ UZQFT UIBU IBWF JOTUBODFT PG UIF Foldable


UZQFDMBTT ƈ CVU SJHIU OPX MJTUT BSF UIF POMZ POF XF DBSF BCPVU

#VU XIBU EP UIFTF UZQFT NFBO )FSFƊT IPX XF DBO CSFBL JU


EPXO

(++) :: [a] -> [a] -> [a]


-- [1] [2] [3]

&WFSZUIJOH BǒFS UIF :: JT BCPVU PVS UZQFT OPU PVS WBMVFT


5IF ƉBƊ JOTJEF UIF MJTU UZQF DPOTUSVDUPS [] JT B UZQF WBSJBCMF

 5BLF BO BSHVNFOU PG UZQF [a] 5IJT UZQF JT B MJTU PG FMF


NFOUT PG TPNF UZQF Ԑ 5IJT GVODUJPO EPFT OPU LOPX XIBU
UZQF Ԑ JT *U EPFTOƊU OFFE UP LOPX *O UIF DPOUFYU PG UIF
QSPHSBN UIF UZQF PG Ԑ XJMM CF LOPXO BOE NBEF DPODSFUF
BU TPNF QPJOU

 5BLF BOPUIFS BSHVNFOU PG UZQF [a] B MJTU PG FMFNFOUT


XIPTF UZQF XF EPOƊU LOPX #FDBVTF UIF WBSJBCMFT BSF UIF
TBNF UIFZ NVTU CF UIF TBNF UZQF UISPVHIPVU B  B


 3FUVSO B SFTVMU PG UZQF [a]

"T XFƊMM TFF CFDBVTF String JT B UZQF PG MJTU UIF PQFSBUPST


XF VTF XJUI TUSJOHT DBO BMTP CF VTFE PO MJTUT PG PUIFS UZQFT
TVDI BT MJTUT PG OVNCFST 5IF UZQF [a] NFBOT UIBU XF IBWF
B MJTU XJUI FMFNFOUT PG B UZQF Ԑ XF EP OPU ZFU LOPX *G XF
VTF UIF PQFSBUPST UP DPODBUFOBUF MJTUT PG OVNCFST UIFO UIF
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

Ԑ JO [a] XJMM CF TPNF UZQF PG OVNCFS GPS FYBNQMF JOUFHFST



*G XF BSF DPODBUFOBUJOH MJTUT PG DIBSBDUFST UIFO Ԑ SFQSFTFOUT
B $IBS CFDBVTF 4USJOH JT [Char] 5IF UZQF WBSJBCMF Ԑ JO [a]
JT QPMZNPSQIJD 1PMZNPSQIJTN JT BO JNQPSUBOU GFBUVSF PG
)BTLFMM 'PS DPODBUFOBUJPO FWFSZ MJTU NVTU CF UIF TBNF UZQF
PG MJTU XF DBOOPU DPODBUFOBUF B MJTU PG OVNCFST XJUI B MJTU PG
DIBSBDUFST GPS FYBNQMF )PXFWFS TJODF UIF Ԑ JT B WBSJBCMF BU
UIF UZQF MFWFM UIF MJUFSBM WBMVFT JO FBDI MJTU XF DPODBUFOBUF
OFFE OPU CF UIF TBNF POMZ UIF TBNF UZQF *O PUIFS XPSET Ԑ
NVTU FRVBM Ԑ B  B


Prelude> "hello" ++ " Chris"


"hello Chris"

-- but

Prelude> "hello" ++ [1, 2, 3]

<interactive>:14:13:
No instance for (Num Char) arising
from the literal ‘1’
In the expression: 1
In the second argument of ‘(++)’,
namely ‘[1, 2, 3]’
In the expression: "hello" ++ [1, 2, 3]
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

*O UIF ƶSTU FYBNQMF XF IBWF UXP TUSJOHT TP UIF UZQF PG Ԑ


NBUDIFT ƈ UIFZƊSF CPUI $IBS JO [Char] FWFO UIPVHI UIF MJUFSBM
WBMVFT BSF EJƵFSFOU 4JODF UIF UZQF NBUDIFT OP UZQF FSSPS
PDDVST BOE XF TFF UIF DPODBUFOBUFE SFTVMU
*O UIF TFDPOE FYBNQMF XF IBWF UXP MJTUT B 4USJOH BOE B
MJTU PG OVNCFST
XIPTF UZQFT EP OPU NBUDI TP XF HFU UIF
FSSPS NFTTBHF ()$J BTLT GPS BO JOTUBODF PG UIF OVNFSJD
UZQFDMBTT Num GPS UIF UZQF Char 8F XJMM EJTDVTT UZQFDMBTTFT MBUFS
5ZQFDMBTTFT QSPWJEF EFƶOJUJPOT PG PQFSBUJPOT PS GVODUJPOT
UIBU DBO CF TIBSFE BDSPTT TFUT PG UZQFT 'PS OPX ZPV DBO
VOEFSTUBOE UIJT NFTTBHF BT UFMMJOH ZPV UIF UZQFT EPOƊU NBUDI
TP JU DBOƊU DPODBUFOBUF UIF UXP MJTUT

&YFSDJTFT 4ZOUBY &SSPST


3FBE UIF TZOUBY PG UIF GPMMPXJOH GVODUJPOT BOE EFDJEF XIFUIFS
JU XJMM DPNQJMF 5FTU UIFN JO ZPVS 3&1- BOE USZ UP ƶY UIF
TZOUBY FSSPST XIFSF UIFZ PDDVS

 ++ [1, 2, 3] [4, 5, 6]

 '<3' ++ ' Haskell'

 concat ["<3", " Haskell"]


$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

 $PODBUFOBUJPO BOE TDPQJOH


8F XJMM VTF QBSFOUIFTFT UP DBMM ++ BT B QSFƶY OPU JOƶY
GVODUJPO

-- print3flipped.hs
module Print3Flipped where

myGreeting :: String
myGreeting = (++) "hello" " world!"

hello :: String
hello = "hello"

world :: String
world = "world!"

main :: IO ()
main = do
putStrLn myGreeting
putStrLn secondGreeting
where secondGreeting =
(++) hello ((++) " " world)
-- could've been:
-- secondGreeting = hello ++ " " ++ world
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

*O secondGreeting VTJOH ++ BT B QSFƶY GVODUJPO GPSDFT VT UP


TIJǒ TPNF UIJOHT BSPVOE 1BSFOUIFTJ[JOH JU UIBU XBZ FNQIB
TJ[FT UIF SJHIU BTTPDJBUJWJUZ PG UIF ++ GVODUJPO 4JODF JUƊT BO JOƶY
PQFSBUPS ZPV DBO DIFDL GPS ZPVSTFMG UIBU JUƊT SJHIU BTTPDJBUJWF

Prelude> :i (++)
(++) :: [a] -> [a] -> [a] -- Defined in ‘GHC.Base’
infixr 5 ++

5IF where DMBVTF DSFBUFT MPDBM CJOEJOHT GPS FYQSFTTJPOT UIBU


BSF OPU WJTJCMF BU UIF UPQ MFWFM *O PUIFS XPSET UIF where DMBVTF
JO UIF NBJO GVODUJPO JOUSPEVDFT B EFƶOJUJPO WJTJCMF POMZ XJUIJO
UIF FYQSFTTJPO PS GVODUJPO JUƊT BUUBDIFE UP SBUIFS UIBO NBL
JOH JU WJTJCMF UP UIF FOUJSF NPEVMF 4PNFUIJOH WJTJCMF BU UIF
UPQ MFWFM JT JO TDPQF GPS BMM QBSUT PG UIF NPEVMF BOE NBZ CF
FYQPSUFE CZ UIF NPEVMF PS JNQPSUFE CZ B EJƵFSFOU NPEVMF
-PDBM EFƶOJUJPOT PO UIF PUIFS IBOE BSF POMZ WJTJCMF UP UIBU
POF GVODUJPO :PV DBOOPU JNQPSU JOUP B EJƵFSFOU NPEVMF BOE
SFVTF secondGreeting
5P JMMVTUSBUF
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

-- print3broken.hs
module Print3Broken where

printSecond :: IO ()
printSecond = do
putStrLn greeting

main :: IO ()
main = do
putStrLn greeting
printSecond
where greeting = "Yarrrrr"

:PV TIPVME HFU BO FSSPS MJLF UIJT

Prelude> :l print3broken.hs
[1 of 1] Compiling Print3Broken ( print3broken.hs, interpreted

print3broken.hs:6:12: Not in scope: ‘greeting’


Failed, modules loaded: none.

-FUƊT UBLF B DMPTFS MPPL BU UIJT FSSPS

print3broken.hs:6:12: Not in scope: ‘greeting’


# [1][2] [3] [4]

 5IF MJOF UIF FSSPS PDDVSSFE PO JO UIJT DBTF MJOF 


$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

 5IF DPMVNO UIF FSSPS PDDVSSFE PO DPMVNO  5FYU


PO DPNQVUFST JT PǒFO EFTDSJCFE JO UFSNT PG MJOFT BOE
DPMVNOT 5IFTF MJOF BOE DPMVNO OVNCFST BSF BCPVU MJOFT
BOE DPMVNOT JO ZPVS UFYU ƶMF DPOUBJOJOH UIF TPVSDF DPEF

 5IF BDUVBM QSPCMFN 8F SFGFS UP TPNFUIJOH OPU JO TDPQF


UIBU JT OPU WJTJCMF UP UIF printSecond GVODUJPO

 5IF UIJOH XF SFGFSSFE UP UIBU JTOƊU WJTJCMF PS JO TDPQF

/PX NBLF UIF Print3Broken DPEF DPNQJMF *U TIPVME QSJOU


ƌ:BSSSSSƍ UXJDF PO UXP EJƵFSFOU MJOFT BOE UIFO FYJU

 .PSF MJTU GVODUJPOT


4JODF B String JT B TQFDJBMJ[FE UZQF PG MJTU ZPV DBO VTF TUBOEBSE
MJTU PQFSBUJPOT PO TUSJOHT BT XFMM
)FSF BSF TPNF FYBNQMFT

Prelude> :t 'c'
'c' :: Char
Prelude> :t "c"
"c" :: [Char] -- List of Char is String, same thing.

-- the : operator, called "cons," builds a list


Prelude> 'c' : "hris"
"chris"
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

Prelude> 'P' : ""


"P"

-- head returns the head or first element of a list


Prelude> head "Papuchon"
'P'

-- tail returns the list with the head chopped off


Prelude> tail "Papuchon"
"apuchon"

-- take returns the specified number of elements


-- from the list, starting from the left:
Prelude> take 1 "Papuchon"
"P"
Prelude> take 0 "Papuchon"
""
Prelude> take 6 "Papuchon"
"Papuch"

-- drop returns the remainder of the list after the


-- specified number of elements has been dropped:
Prelude> drop 4 "Papuchon"
"chon"
Prelude> drop 9001 "Papuchon"
""
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

Prelude> drop 1 "Papuchon"


"apuchon"

-- we've already seen the ++ operator


Prelude> "Papu" ++ "chon"
"Papuchon"
Prelude> "Papu" ++ ""
"Papu"

-- !! returns the element that is in the specified


-- position in the list. Note that this is an
-- indexing function, and indices in Haskell start
-- from 0. That means the first element of your
-- list is 0, not 1, when using this function.
Prelude> "Papuchon" !! 0
'P'
Prelude> "Papuchon" !! 4
'c'

/PUF UIBU XIJMF BMM UIFTF GVODUJPOT BSF TUBOEBSE 1SFMVEF


GVODUJPOT NBOZ PG UIFN BSF DPOTJEFSFE VOTBGF 5IFZ BSF VO
TBGF CFDBVTF UIFZ EP OPU DPWFS UIF DBTF XIFSF UIFZ BSF HJWFO
BO FNQUZ MJTU BT JOQVU *OTUFBE UIFZ KVTU UISPX PVU BO FSSPS
NFTTBHF PS FYDFQUJPO

Prelude> head ""


$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

*** Exception: Prelude.head: empty list


Prelude> "" !! 4
*** Exception: Prelude.!!: index too large

5IJT JTOƊU JEFBM CFIBWJPS TP UIF VTF PG UIFTF GVODUJPOT JT


DPOTJEFSFE VOXJTF GPS QSPHSBNT PG BOZ SFBM TJ[F PS DPNQMFYJUZ
BMUIPVHI XF XJMM VTF UIFN JO UIFTF ƶSTU GFX DIBQUFST 8F XJMM
BEESFTT IPX UP DPWFS BMM DBTFT BOE NBLF TBGFS WFSTJPOT PG TVDI
GVODUJPOT JO B MBUFS DIBQUFS

 $IBQUFS &YFSDJTFT


3FBEJOH TZOUBY
 'PS UIF GPMMPXJOH MJOFT PG DPEF SFBE UIF TZOUBY DBSFGVMMZ
BOE EFDJEF JG UIFZ BSF XSJUUFO DPSSFDUMZ 5FTU UIFN JO ZPVS
3&1- BǒFS ZPVƊWF EFDJEFE UP DIFDL ZPVS XPSL $PSSFDU
BT NBOZ BT ZPV DBO

B
concat [[1, 2, 3], [4, 5, 6]]

C
++ [1, 2, 3] [4, 5, 6]

D
(++) "hello" " world"

E
["hello" ++ " world]

F
4 !! "hello"

G
(!!) "hello" 4
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

H
take "4 lovely"

I
take 3 "awesome"

 /FYU XF IBWF UXP TFUT UIF ƶSTU TFU JT MJOFT PG DPEF BOE
UIF PUIFS JT B TFU PG SFTVMUT 3FBE UIF DPEF BOE ƶHVSF PVU
XIJDI SFTVMUT DBNF GSPN XIJDI MJOFT PG DPEF #F TVSF UP
UFTU UIFN JO UIF 3&1-

B
concat [[1 * 6], [2 * 6], [3 * 6]]

C
"rain" ++ drop 2 "elbow"

D
10 * head [1, 2, 3]

E
(take 3 "Julie") ++ (tail "yes")

F
concat [tail [1, 2, 3],
tail [4, 5, 6],
tail [7, 8, 9]]

$BO ZPV NBUDI FBDI PG UIF QSFWJPVT FYQSFTTJPOT UP POF


PG UIFTF SFTVMUT QSFTFOUFE JO B TDSBNCMFE PSEFS

B
"Jules"
C
[2,3,5,6,8,9]
D
"rainbow"
E
[6,12,18]
F
10
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

#VJMEJOH GVODUJPOT
 (JWFO UIF MJTUNBOJQVMBUJPO GVODUJPOT NFOUJPOFE JO UIJT
DIBQUFS XSJUF GVODUJPOT UIBU UBLF UIF GPMMPXJOH JOQVUT BOE
SFUVSO UIF FYQFDUFE PVUQVUT %P UIFN EJSFDUMZ JO ZPVS
3&1- BOE VTF UIF take BOE drop GVODUJPOT ZPVƊWF BMSFBEZ
TFFO

&YBNQMF

-- If you apply your function to this value:


"Hello World"
-- Your function should return:
"ello World"

5IF GPMMPXJOH XPVME CF B ƶOF TPMVUJPO

Prelude> drop 1 "Hello World"


"ello World"

/PX XSJUF FYQSFTTJPOT UP QFSGPSN UIF GPMMPXJOH USBOT


GPSNBUJPOT KVTU XJUI UIF GVODUJPOT ZPVƊWF TFFO JO UIJT
DIBQUFS :PV EP OPU OFFE UP EP BOZUIJOH DMFWFS IFSF

B
-- Given
"Curry is awesome"
-- Return
"Curry is awesome!"
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

C
-- Given
"Curry is awesome!"
-- Return
"y"

D
-- Given
"Curry is awesome!"
-- Return
"awesome!"

 /PX UBLF FBDI PG UIF BCPWF BOE SFXSJUF JU JO B TPVSDF


ƶMF BT B HFOFSBM GVODUJPO UIBU DPVME UBLF EJƵFSFOU TUSJOH
JOQVUT BT BSHVNFOUT CVU SFUBJO UIF TBNF CFIBWJPS 6TF
B WBSJBCMF BT UIF BSHVNFOU UP ZPVS OBNFE
GVODUJPOT *G
ZPVƊSF VOTVSF IPX UP EP UIJT SFGSFTI ZPVS NFNPSZ CZ
MPPLJOH BU UIF waxOff FYFSDJTF GSPN UIF QSFWJPVT DIBQUFS
BOE UIF TopOrLocal NPEVMF GSPN UIJT DIBQUFS

 8SJUF B GVODUJPO PG UZQF String -> Char XIJDI SFUVSOT UIF


UIJSE DIBSBDUFS JO B 4USJOH 3FNFNCFS UP HJWF UIF GVODUJPO
B OBNF BOE BQQMZ JU UP B WBSJBCMF OPU B TQFDJƶD 4USJOH
TP UIBU JU DPVME CF SFVTFE GPS EJƵFSFOU 4USJOH JOQVUT BT
EFNPOTUSBUFE GFFM GSFF UP OBNF UIF GVODUJPO TPNFUIJOH
FMTF #F TVSF UP ƶMM JO UIF UZQF TJHOBUVSF BOE ƶMM JO UIF
GVODUJPO EFƶOJUJPO BǒFS UIF FRVBMT TJHO

$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

thirdLetter ::
thirdLetter x =

-- If you apply your function to this value:


"Curry is awesome"
-- Your function should return
`r'

/PUF UIBU QSPHSBNNJOH MBOHVBHFT DPOWFOUJPOBMMZ TUBSU


JOEFYJOH UIJOHT CZ [FSP TP HFUUJOH UIF [FSPUI JOEFY PG B
TUSJOH XJMM HFU ZPV UIF ƶSTU MFUUFS "DDPSEJOHMZ JOEFYJOH
XJUI  XJMM BDUVBMMZ HFU ZPV UIF GPVSUI ,FFQ UIJT JO NJOE
BT ZPV XSJUF UIJT GVODUJPO

 /PX DIBOHF UIBU GVODUJPO TP UIF TUSJOH PQFSBUFE PO JT


BMXBZT UIF TBNF BOE UIF WBSJBCMF SFQSFTFOUT UIF OVNCFS
PG UIF MFUUFS ZPV XBOU UP SFUVSO ZPV DBO VTF ƌ$VSSZ JT
BXFTPNFƍ BT ZPVS TUSJOH JOQVU PS B EJƵFSFOU TUSJOH JG ZPV
QSFGFS


letterIndex :: Int -> Char


letterIndex x =

 6TJOH UIF take BOE drop GVODUJPOT XF MPPLFE BU BCPWF TFF


JG ZPV DBO XSJUF B GVODUJPO DBMMFE rvrs BO BCCSFWJBUJPO PG
ƉSFWFSTFƊ VTFE CFDBVTF UIFSF JT B GVODUJPO DBMMFE ƉSFWFSTFƊ
BMSFBEZ JO 1SFMVEF TP JG ZPV DBMM ZPVS GVODUJPO UIF TBNF
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

OBNF ZPVƊMM HFU BO FSSPS NFTTBHF


 rvrs TIPVME UBLF UIF
TUSJOH ƌ$VSSZ JT BXFTPNFƍ BOE SFUVSO UIF SFTVMU ƌBXFTPNF
JT $VSSZƍ 5IJT NBZ OPU CF UIF NPTU MPWFMZ )BTLFMM DPEF
ZPV XJMM FWFS XSJUF CVU JU JT RVJUF QPTTJCMF VTJOH POMZ XIBU
XFƊWF MFBSOFE TP GBS 'JSTU XSJUF JU BT B TJOHMF GVODUJPO JO
B TPVSDF ƶMF 5IJT EPFTOƊU OFFE UP BOE TIPVMEOƊU XPSL
GPS SFWFSTJOH UIF XPSET PG BOZ TFOUFODF :PVƊSF FYQFDUFE
POMZ UP TMJDF BOE EJDF UIJT QBSUJDVMBS TUSJOH XJUI take BOE
drop

 -FUƊT TFF JG XF DBO FYQBOE UIBU GVODUJPO JOUP B NPEVMF


8IZ XPVME XF XBOU UP #Z FYQBOEJOH JU JOUP B NPEVMF
XF DBO BEE NPSF GVODUJPOT MBUFS UIBU DBO JOUFSBDU XJUI
FBDI PUIFS 8F DBO BMTP UIFO FYQPSU JU UP PUIFS NPEVMFT
JG XF XBOU UP BOE VTF UIJT DPEF JO UIPTF PUIFS NPEVMFT
5IFSF BSF EJƵFSFOU XBZT ZPV DPVME MBZ JU PVU CVU GPS UIF
TBLF PG DPOWFOJFODF XFƊMM TIPX ZPV B TBNQMF MBZPVU TP
UIBU ZPV DBO ƶMM JO UIF CMBOLT

module Reverse where

rvrs :: String -> String


rvrs x =

main :: IO ()
main = print ()
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

*OUP UIF QBSFOUIFTFT BǒFS print ZPVƊMM OFFE UP ƶMM JO ZPVS


GVODUJPO OBNF rvrs QMVT UIF BSHVNFOU ZPVƊSF BQQMZJOH
rvrs UP JO UIJT DBTF ƌ$VSSZ JT BXFTPNFƍ 5IBU rvrs GVODUJPO
QMVT JUT BSHVNFOU BSF OPX UIF BSHVNFOU UP print *UƊT
JNQPSUBOU UP QVU UIFN JOTJEF UIF QBSFOUIFTFT TP UIBU UIBU
GVODUJPO HFUT BQQMJFE BOE FWBMVUFE ƶSTU BOE UIFO UIBU
SFTVMU JT QSJOUFE
0G DPVSTF XF IBWF BMTP NFOUJPOFE UIBU ZPV DBO VTF UIF $
TZNCPM UP BWPJE VTJOH QBSFOUIFTFT UPP 5SZ NPEJGZJOH
ZPVS NBJO GVODUJPO UP VTF UIBU JOTUFBE PG UIF QBSFOUIFTFT

 %FƶOJUJPOT
 " 4USJOH JT B TFRVFODF PG DIBSBDUFST *O )BTLFMM String JT
SFQSFTFOUFE CZ B MJOLFEMJTU PG Char WBMVFT BLB [Char]

 " UZQF PS EBUBUZQF JT B DMBTTJƶDBUJPO PG WBMVFT PS EBUB


5ZQFT JO )BTLFMM EFUFSNJOF XIBU WBMVFT BSF NFNCFST
PG UIF UZQF PS UIBU JOIBCJU UIF UZQF 6OMJLF JO PUIFS MBO
HVBHFT EBUBUZQFT JO )BTLFMM CZ EFGBVMU EP OPU EFMJNJU UIF
PQFSBUJPOT UIBU DBO CF QFSGPSNFE PO UIBU EBUB

 $PODBUFOBUJPO JT UIF KPJOJOH UPHFUIFS PG TFRVFODFT PG WBM


VFT 0ǒFO JO )BTLFMM UIJT JT NFBOU XJUI SFTQFDU UP UIF []
PS ƌ-JTUƍ EBUBUZQF XIJDI BMTP BQQMJFT UP String XIJDI JT
$)"15&3  4*.1-& 01&3"5*0/4 8*5) 5&95 

[Char] 5IF DPODBUFOBUJPO GVODUJPO JO )BTLFMM JT (++) XIJDI


IBT UZQF [a] -> [a] -> [a] 'PS FYBNQMF

Prelude> "tacos" ++ " " ++ "rock"


"tacos rock"

 4DPQF JT XIFSF B WBSJBCMF SFGFSSFE UP CZ OBNF JT WBMJE


"OPUIFS XPSE VTFE XJUI UIF TBNF NFBOJOH JT WJTJCJMJUZ
CFDBVTF JG B WBSJBCMF JTOƊU WJTJCMF JUƊT OPU JO TDPQF

 -PDBM CJOEJOHT BSF CJOEJOHT MPDBM UP QBSUJDVMBS FYQSFTTJPOT


5IF QSJNBSZ EFMJOFBUJPO IFSF GSPN UPQ MFWFM CJOEJOHT JT
UIBU MPDBM CJOEJOHT DBOOPU CF JNQPSUFE CZ PUIFS QSPHSBNT
PS NPEVMFT

 5PQ MFWFM CJOEJOHT JO )BTLFMM BSF CJOEJOHT UIBU TUBOE PVUTJEF


PG BOZ PUIFS EFDMBSBUJPO 5IF NBJO GFBUVSF PG UPQMFWFM
CJOEJOHT JT UIBU UIFZ DBO CF NBEF BWBJMBCMF UP PUIFS NPE
VMFT XJUIJO ZPVS QSPHSBNT PS UP PUIFS QFPQMFƊT QSPHSBNT

 %BUB TUSVDUVSFT BSF B XBZ PG PSHBOJ[JOH EBUB TP UIBU UIF


EBUB DBO CF BDDFTTFE DPOWFOJFOUMZ PS FƸDJFOUMZ
$IBQUFS 

#BTJD EBUBUZQFT

5IFSF BSF NBOZ XBZT PG


USZJOH UP VOEFSTUBOE
QSPHSBNT 1FPQMF PǒFO
SFMZ UPP NVDI PO POF
XBZ XIJDI JT DBMMFE
ƌEFCVHHJOHƍ BOE DPOTJTUT
PG SVOOJOH B
QBSUMZVOEFSTUPPE
QSPHSBN UP TFF JG JU EPFT
XIBU ZPV FYQFDUFE
"OPUIFS XBZ XIJDI .-
BEWPDBUFT JT UP JOTUBMM
TPNF NFBOT PG
VOEFSTUBOEJOH JO UIF WFSZ
QSPHSBNT UIFNTFMWFT

3PCJO .JMOFS


$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

 #BTJD %BUBUZQFT


)BTLFMM IBT B SPCVTU BOE FYQSFTTJWF UZQF TZTUFN 5ZQFT QMBZ BO
JNQPSUBOU SPMF JO UIF SFBEBCJMJUZ TBGFUZ BOE NBJOUBJOBCJMJUZ PG
)BTLFMM DPEF BT UIFZ BMMPX VT UP DMBTTJGZ BOE EFMJNJU EBUB UIVT
SFTUSJDUJOH UIF GPSNT PG EBUB PVS QSPHSBNT DBO QSPDFTT 5ZQFT
BMTP DBMME EBUBUZQFT QSPWJEF UIF NFBOT UP CVJME QSPHSBNT NPSF
RVJDLMZ BOE BMTP BMMPX GPS HSFBUFS FBTF PG NBJOUFOBODF "T XF
MFBSO NPSF )BTLFMM XFƊMM MFBSO IPX UP MFWFSBHF UZQFT JO B XBZ
UIBU MFUT VT BDDPNQMJTI UIF TBNF UIJOHT CVU XJUI MFTT DPEF
4P GBS XFƊWF MPPLFE BU FYQSFTTJPOT JOWPMWJOH OVNCFST DIBS
BDUFST BOE MJTUT PG DIBSBDUFST BMTP DBMMFE TUSJOHT 5IFTF BSF
TPNF PG UIF TUBOEBSE CVJMUJO EBUBUZQFT UIBU DBUFHPSJ[F BOE
EFMJNJU WBMVFT 8IJMF UIPTF BSF VTFGVM EBUBUZQFT BOE DPWFS B
MPU PG UZQFT PG WBMVFT UIFZ DFSUBJOMZ EPOƊU DPWFS FWFSZ UZQF PG
EBUB *O UIJT DIBQUFS XF XJMM

Ƒ SFWJFX UZQFT XF IBWF TFFO JO QSFWJPVT DIBQUFST

Ƒ MFBSO BCPVU EBUBUZQFT UZQF DPOTUSVDUPST BOE EBUB DPO


TUSVDUPST

Ƒ XPSL XJUI QSFEFƶOFE EBUBUZQFT

Ƒ MFBSO NPSF BCPVU UZQF TJHOBUVSFT BOE B CJU BCPVU UZQF


DMBTTFT
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

 8IBU BSF UZQFT


&YQSFTTJPOT XIFO FWBMVBUFE SFEVDF UP WBMVFT &WFSZ WBMVF
IBT B UZQF 5ZQFT BSF IPX XF HSPVQ B TFU PG WBMVFT UPHFUIFS
UIBU TIBSF TPNFUIJOH JO DPNNPO 4PNFUJNFT UIBU ƌTPNFUIJOH
JO DPNNPOƍ JT BCTUSBDU TPNFUJNFT JUƊT B TQFDJƶD NPEFM PG B
QBSUJDVMBS DPODFQU PS EPNBJO *G ZPVƊWF UBLFO B NBUIFNBUJDT
DPVSTF UIBU DPWFSFE TFUT UIJOLJOH BCPVU UZQFT BT CFJOH MJLF
TFUT XJMM IFMQ HVJEF ZPVS JOUVJUJPO PO XIBU UZQFT BSF BOE IPX
UIFZ XPSL JO B NBUIFNBUJDBM TFOTF

 "OBUPNZ PG B EBUB EFDMBSBUJPO


%BUB EFDMBSBUJPOT BSF IPX EBUBUZQFT BSF EFƶOFE
5IF UZQF DPOTUSVDUPS JT UIF OBNF PG UIF UZQF BOE JT DBQJ
UBMJ[FE 8IFO ZPV BSF SFBEJOH PS XSJUJOH UZQF TJHOBUVSFT UIF
UZQF MFWFM PG ZPVS DPEF
UIF UZQF OBNFT PS UZQF DPOTUSVDUPST
BSF XIBU ZPV VTF
%BUB DPOTUSVDUPST BSF UIF WBMVFT UIBU JOIBCJU UIF UZQF UIFZ
BSF EFƶOFE JO 5IFZ BSF UIF WBMVFT UIBU TIPX VQ JO ZPVS DPEF
BU UIF UFSN MFWFM JOTUFBE PG UIF UZQF MFWFM #Z ƌUFSN MFWFMƍ XF
NFBO UIFZ BSF UIF WBMVFT BT UIFZ BQQFBS JO ZPVS DPEF PS UIF
WBMVFT UIBU ZPVS DPEF FWBMVBUFT UP

4FU UIFPSZ JT UIF TUVEZ PG NBUIFNBUJDBM DPMMFDUJPOT PG PCKFDUT 4FU UIFPSZ XBT B
QSFDVSTPS UP UZQF UIFPSZ UIF MBUUFS CFJOH VTFE QSPMJƶDBMMZ JO UIF EFTJHO PG QSPHSBNNJOH
MBOHVBHFT MJLF )BTLFMM -PHJDBM PQFSBUJPOT MJLF EJTKVODUJPO PS
BOE DPOKVODUJPO BOE
VTFE
JO UIF NBOJQVMBUJPO PG TFUT IBWF FRVJWBMFOUT JO )BTLFMMƊT UZQF TZTUFN
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

8F XJMM TUBSU XJUI B CBTJD EBUBUZQF UP TFF IPX EBUBUZQFT BSF


TUSVDUVSFE BOE HFU BDRVBJOUFE XJUI UIF WPDBCVMBSZ Bool JTOƊU B
EBUBUZQF XFƊWF TFFO ZFU JO UIF CPPL CVU JU QSPWJEFT GPS USVUI
WBMVFT *U JT OBNFE BǒFS UIF HSFBU MPHJDJBO (FPSHF #PPMF BOE
UIF TZTUFN PG MPHJD OBNFE GPS IJN #FDBVTF UIFSF BSF POMZ
UXP USVUI WBMVFT JUƊT FBTZ UP MJTU BMM UIF EBUB DPOTUSVDUPST

-- the definition of Bool


data Bool = False | True
-- [1] [2] [3] [4]

 5ZQF DPOTUSVDUPS GPS EBUBUZQF Bool 5IJT JT UIF OBNF PG


UIF UZQF BOE TIPXT VQ JO UZQF TJHOBUVSFT

 %BUB DPOTUSVDUPS GPS UIF WBMVF False

 1JQF | JOEJDBUFT B TVN UZQF PS MPHJDBM EJTKVODUJPO ƌPSƍ 4P


B Bool WBMVF JT True PS False

 %BUB DPOTUSVDUPS GPS UIF WBMVF True

5IF XIPMF UIJOH JT DBMMFE B EBUB EFDMBSBUJPO %BUB EFDMBSB


UJPOT EP OPU BMXBZT GPMMPX QSFDJTFMZ UIF TBNF QBUUFSO ƈ UIFSF
BSF EBUBUZQFT UIBU VTF MPHJDBM DPOKVODUJPO ƌBOEƍ
JOTUFBE PG
EJTKVODUJPO BOE TPNF UZQF DPOTUSVDUPST BOE EBUB DPOTUSVDUPST
NBZ IBWF BSHVNFOUT 5IF UIJOH UIFZ IBWF JO DPNNPO JT UIF
LFZXPSE data GPMMPXFE CZ UIF UZQF DPOTUSVDUPS PS OBNF PG
UIF UZQF UIBU XJMM BQQFBS JO UZQF TJHOBUVSFT
UIF FRVBMT TJHO UP
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

EFOPUF B EFƶOJUJPO BOE UIFO EBUB DPOTUSVDUPST PS OBNFT PG


WBMVFT UIBU JOIBCJU ZPVS UFSNMFWFM DPEF

:PV DBO ƶOE UIF EBUBUZQF EFƶOJUJPO GPS CVJMUJO EBUBUZQFT
CZ VTJOH :info JO ()$J

Prelude> :info Bool


data Bool = False | True

-FUƊT MPPL BU XIFSF EJƵFSFOU QBSUT PG EBUBUZQFT TIPX VQ


JO PVS DPEF *G XF RVFSZ UIF UZQF JOGPSNBUJPO GPS B GVODUJPO
DBMMFE not XF TFF UIBU JU UBLFT POF Bool WBMVF BOE SFUVSOT BOPUIFS
Bool WBMVF TP UIF UZQF TJHOBUVSF NBLFT SFGFSFODF UP UIF UZQF
DPOTUSVDUPS PS EBUBUZQF OBNF

Prelude> :t not
not :: Bool -> Bool

#VU XIFO XF VTF UIF not GVODUJPO XF VTF UIF EBUB DPOTUSVD
UPST PS WBMVFT

Prelude> not True


False

"OE PVS FYQSFTTJPO FWBMVBUFT UP BOPUIFS EBUB DPOTUSVDUPS


PS WBMVF ƈ JO UIJT DBTF UIF PUIFS EBUB DPOTUSVDUPS GPS UIF TBNF
EBUBUZQF
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

&YFSDJTFT .PPE 4XJOH


(JWFO UIF GPMMPXJOH EBUBUZQF BOTXFS UIF GPMMPXJOH RVFTUJPOT

data Mood = Blah | Woot deriving Show

5IF deriving Show QBSU JT OPU TPNFUIJOH XFƊWF FYQMBJOFE


ZFU 'PS OPX BMM XFƊMM TBZ JT UIBU XIFO ZPV NBLF ZPVS PXO
EBUBUZQFT EFSJWJOH Show BMMPXT UIF WBMVFT PG UIBU UZQF UP CF
QSJOUFE UP UIF TDSFFO 8FƊMM UBML BCPVU JU NPSF XIFO XF UBML
BCPVU UZQFDMBTTFT JO EFUBJM

 8IBU JT UIF UZQF DPOTUSVDUPS PS OBNF PG UIJT UZQF

 *G UIF GVODUJPO SFRVJSFT B Mood WBMVF XIBU BSF UIF WBMVFT


ZPV DPVME QPTTJCMZ VTF UIFSF

 8F BSF USZJOH UP XSJUF B GVODUJPO changeMood UP DIBOHF


$ISJTƊT NPPE JOTUBOUBOFPVTMZ *U TIPVME BDU MJLF not JO
UIBU HJWFO POF WBMVF JU SFUVSOT UIF PUIFS WBMVF PG UIF TBNF
UZQF 4P GBS XFƊWF XSJUUFO B UZQF TJHOBUVSF changeMood ::
Mood -> Woot 8IBUƊT XSPOH XJUI UIBU

 /PX XF XBOU UP XSJUF UIF GVODUJPO UIBU DIBOHFT IJT NPPE


(JWFO BO JOQVU NPPE JU HJWFT VT UIF PUIFS POF 'JY BOZ
NJTUBLFT BOE DPNQMFUF UIF GVODUJPO

changeMood Mood = Woot


changeMood _ = Blah
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

8FƊSF EPJOH TPNFUIJOH IFSF DBMMFE QBUUFSO NBUDIJOH 8F


DBO EFƶOF B GVODUJPO CZ NBUDIJOH PO B EBUB DPOTUSVDUPS
PS WBMVF BOE EFTDSCJOH UIF CFIBWJPS UIF GVODUJPO TIPVME
IBWF CBTFE PO XIJDI WBMVF JU NBUDIFT 5IF VOEFSTDPSF
JO UIF TFDPOE MJOF EFOPUFT B DBUDIBMM PUIFSXJTF DBTF 4P
JO UIF ƶSTU MJOF PG UIF GVODUJPO XFƊSF UFMMJOH JU XIBU UP EP
JO UIF DBTF PG B TQFDJƶD JOQVU *O UIF TFDPOE POF XFƊSF
UFMMJOH JU XIBU UP EP SFHBSEMFTT PG BMM QPUFOUJBM JOQVUT *UƊT
USJWJBM XIFO UIFSF BSF POMZ UXP QPUFOUJBM WBMVFT PG B HJWFO
UZQF CVU BT XF EFBM XJUI NPSF DPNQMFY DBTFT JU DBO CF
DPOWFOJFOU 8FƊMM UBML BCPVU QBUUFSO NBUDIJOH JO HSFBUFS
EFUBJM JO B MBUFS DIBQUFS

 &OUFS BMM PG UIF BCPWF ƈ EBUBUZQF JODMVEJOH UIF deriving


Show CJU
ZPVS DPSSFDUFE UZQF TJHOBUVSF BOE UIF DPSSFDUFE
GVODUJPO JOUP B TPVSDF ƶMF -PBE JU BOE SVO JU JO ()$J UP
NBLF TVSF ZPV HPU JU SJHIU

 /VNFSJD UZQFT


-FUƊT OFYU MPPL BU OVNFSJD UZQFT CFDBVTF XFƊWF BMSFBEZ TFFO
UIFTF UZQFT JO QSFWJPVT DIBQUFST BOE OVNCFST BSF GBNJMJBS
UFSSJUPSZ *UƊT JNQPSUBOU UP VOEFSTUBOE UIBU )BTLFMM EPFT OPU
KVTU VTF POF UZQF PG OVNCFS 'PS NPTU QVSQPTFT UIF UZQFT PG
OVNCFST XF OFFE UP CF DPODFSOFE XJUI BSF
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

*OUFHSBM OVNCFST 5IFTF BSF XIPMF OVNCFST QPTJUJWF BOE


OFHBUJWF

 Int 5IJT UZQF JT B ƶYFEQSFDJTJPO JOUFHFS #Z ƌƶYFE QSF


DJTJPO ƍ XF NFBO JU IBT B SBOHF XJUI B NBYJNVN BOE B
NJOJNVN BOE TP JU DBOOPU CF BSCJUSBSJMZ MBSHF PS TNBMM
ƈ NPSF BCPVU UIJT JO B NPNFOU

 Integer 5IJT UZQF JT BMTP GPS JOUFHFST CVU UIJT POF TVQQPSUT
BSCJUSBSJMZ MBSHF PS TNBMM
OVNCFST

'SBDUJPOBM 5IFTF BSF OPU JOUFHFST Fractional WBMVFT JODMVEF


UIF GPMMPXJOH GPVS UZQFT

 Float 5IJT JT UIF UZQF VTFE GPS TJOHMFQSFDJTJPO ƷPBU


JOH QPJOU OVNCFST 'JYFEQPJOU OVNCFS SFQSFTFOUBUJPOT
IBWF JNNVUBCMF OVNCFST PG EJHJUT BTTJHOFE GPS UIF QBSUT
PG UIF OVNCFS CFGPSF BOE BǒFS UIF EFDJNBM QPJOU *O
DPOUSBTU ƷPBUJOH QPJOU DBO TIJǒ IPX NBOZ CJUT JU VTFT UP
SFQSFTFOU OVNCFST CFGPSF PS BǒFS UIF EFDJNBM QPJOU 5IJT
ƷFYJCJMJUZ EPFT IPXFWFS NFBO UIBU ƷPBUJOH QPJOU BSJUI
NFUJD WJPMBUFT TPNF DPNNPO BTTVNQUJPOT BOE TIPVME
POMZ CF VTFE XJUI HSFBU DBSF (FOFSBMMZ ƷPBUJOH QPJOU
OVNCFST TIPVME OPU CF VTFE BU BMM JO CVTJOFTT BQQMJDBUJPOT

 Double 5IJT JT B EPVCMFQSFDJTJPO ƷPBUJOH QPJOU OVNCFS


UZQF *U IBT UXJDF BT NBOZ CJUT XJUI XIJDI UP EFTDSJCF
OVNCFST BT UIF Float UZQF
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

 Rational 5IJT JT B GSBDUJPOBM OVNCFS UIBU SFQSFTFOUT B


SBUJP PG UXP JOUFHFST 5IF WBMVF 1 / 2 :: Rational XJMM CF B
WBMVF DBSSZJOH UXP Integer WBMVFT UIF OVNFSBUPS  BOE UIF
EFOPNJOBUPS  BOE SFQSFTFOUT B SBUJP PG  UP  Rational JT
BSCJUSBSJMZ QSFDJTF CVU OPU BT FƸDJFOU BT Scientific

 Scientific 5IJT JT B TQBDF FƸDJFOU BOE BMNPTUBSCJUSBSZ


QSFDJTJPO TDJFOUJƶD OVNCFS UZQF Scientific OVNCFST BSF
SFQSFTFOUFE VTJOH TDJFOUJƶD OPUBUJPO *U TUPSFT UIF DPFG
ƶDJFOU BT BO Integer BOE UIF FYQPOFOU BT BO Int 4JODF
Int JTOƊU BSCJUSBSJMZMBSHF UIFSF JT UFDIOJDBMMZ B MJNJU UP
UIF TJ[F PG OVNCFS ZPV DBO FYQSFTT XJUI Scientific CVU
IJUUJOH UIBU MJNJU JT RVJUF VOMJLFMZ Scientific JT BWBJMBCMF
JO B MJCSBSZ

5IFTF OVNFSJD EBUBUZQFT BMM IBWF JOTUBODFT PG B UZQFDMBTT


DBMMFE Num 8F XJMM UBML BCPVU UZQFDMBTTFT JO UIF VQDPNJOH
DIBQUFST CVU BT XF MPPL BU UIF UZQFT JO UIJT TFDUJPO ZPV XJMM
TFF Num MJTUFE JO TPNF PG UIF UZQF JOGPSNBUJPO
5ZQFDMBTTFT BSF B XBZ PG BEEJOH GVODUJPOBMJUZ UP UZQFT UIBU
JT SFVTBCMF BDSPTT BMM UIF UZQFT UIBU IBWF JOTUBODFT PG UIBU UZQF
DMBTT Num JT B UZQFDMBTT GPS XIJDI NPTU OVNFSJD UZQFT XJMM
IBWF BO JOTUBODF CFDBVTF UIFSF BSF TUBOEBSE GVODUJPOT UIBU BSF
DPOWFOJFOU UP IBWF BWBJMBCMF GPS BMM UZQFT PG OVNCFST 5IF Num
UZQFDMBTT JT XIBU QSPWJEFT ZPVS TUBOEBSE (+) (-) BOE (*) PQFS

)BDLBHF QBHF GPS TDJFOUJƶD https://hackage.haskell.org/package/scientific BOE DBO CF
JOTUBMMFE VTJOH cabal install PS stack install
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

BUPST BMPOH XJUI B GFX PUIFST "OZ UZQF UIBU IBT BO JOTUBODF PG
Num DBO CF VTFE XJUI UIPTF GVODUJPOT "O JOTUBODF EFƶOFT IPX
UIF GVODUJPOT XPSL GPS UIBU TQFDJƶD UZQF 8F XJMM UBML BCPVU
UZQFDMBTTFT JO NVDI NPSF EFUBJM TPPO

*OUFHSBM OVNCFST
"T XF OPUFE BCPWF UIFSF BSF UXP NBJO UZQFT PG JOUFHSBM OVN
CFST Int BOE Integer
*OUFHSBM OVNCFST BSF XIPMF OVNCFST XJUI OP GSBDUJPOBM
DPNQPOFOU 5IF GPMMPXJOH BSF JOUFHSBM OVNCFST

1 2 199 32442353464675685678

5IF GPMMPXJOH BSF OPU JOUFHSBM OVNCFST

1.3 1/2

*OUFHFS
5IF OVNCFST PG UZQF Integer BSF TUSBJHIUGPSXBSE FOPVHI GPS
UIF NPTU QBSU UIFZ BSF UIF TPSUT PG OVNCFST XFƊSF BMM VTFE UP
XPSLJOH XJUI JO BSJUINFUJD FRVBUJPOT UIBU JOWPMWF XIPMF OVN
CFST 5IFZ DBO CF QPTJUJWF PS OFHBUJWF BOE Integer FYUFOET BT
GBS JO FJUIFS EJSFDUJPO BT POF OFFET UIFN UP HP
5IF Bool EBUBUZQF POMZ IBT UXP QPTTJCMF WBMVFT TP XF DBO MJTU
UIFN FYQMJDJUMZ BT EBUB DPOTUSVDUPST *O UIF DBTF PG Integer BOE
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

NPTU OVNFSJD EBUBUZQFT UIFTF EBUB DPOTUSVDUPST BSF OPU XSJU


UFO PVU CFDBVTF UIFZ JODMVEF BO JOƶOJUF TFSJFT PG XIPMF OVN
CFST 8FƊE OFFE JOƶOJUF EBUB DPOTUSVDUPST TUSFUDIJOH VQ BOE
EPXO GSPN [FSP )ZQPUIFUJDBMMZ XF DPVME SFQSFTFOU Integer BT
B TVN PG UISFF DBTFT SFDVSTJWF DPOTUSVDUPST IFBEFE UPXBSET
OFHBUJWF JOƶOJUZ [FSP BOE SFDVSTJWF DPOTUSVDUPST IFBEFE UP
XBSET QPTJUJWF JOƶOJUZ 5IJT SFQSFTFOUBUJPO XPVME CF UFSSJCMZ
JOFƸDJFOU TP UIFSFƊT TPNF ()$ NBHJD TQSJOLMFE PO JU

8IZ EP XF IBWF *OU


5IF Int OVNFSJD UZQF JT BO BSUJGBDU PG XIBU DPNQVUFS IBSE
XBSF IBT TVQQPSUFE OBUJWFMZ PWFS UIF ZFBST .PTU QSPHSBNT
TIPVME VTF Integer BOE OPU Int VOMFTT UIF MJNJUBUJPOT PG UIF
UZQF BSF VOEFSTUPPE BOE UIF BEEJUJPOBM QFSGPSNBODF NBLFT B
EJƵFSFODF
5IF EBOHFS PG Int BOE UIF SFMBUFE UZQFT Int8 Int16 FU BM JT
UIBU UIFZ DBOOPU FYQSFTT BSCJUSBSJMZ MBSHF RVBOUJUJFT PG JOGPS
NBUJPO 4JODF UIFZ BSF JOUFHSBM UIJT NFBOT UIFZ DBOOPU CF
BSCJUSBSJMZ MBSHF JO UIF QPTJUJWF PS OFHBUJWF TFOTF
)FSFƊT XIBU IBQQFOT JG XF USZ UP SFQSFTFOU B OVNCFS UPP
MBSHF GPS Int8

Prelude> import GHC.Int


Prelude> 127 :: Int8
127
Prelude> 128 :: Int8
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

<interactive>:11:1: Warning:
Literal 128 is out of the Int8 range -128..127
If you are trying to write a large negative literal,
use NegativeLiterals
-128
Prelude> (127 + 1) :: Int8
-128

5IF TZOUBY ZPV TFF UIFSF :: Int8 JT VT BTTJHOJOH UIF Int8


UZQF UP UIFTF OVNCFST "T XF XJMM FYQMBJO JO NPSF EFUBJM JO
UIF OFYU DIBQUFS OVNCFST BSF QPMZNPSQIJD VOEFSOFBUI BOE
UIF DPNQJMFS EPFTOƊU BTTJHO UIFN B DPODSFUF UZQF VOUJM JU JT
GPSDFE UP *U XPVME CF XFJSE BOE VOFYQFDUFE JG UIF DPNQJMFS
EFGBVMUFE BMM OVNCFST UP Int8 TP JO PSEFS UP SFQSPEVDF UIF
TJUVBUJPO PG IBWJOH B OVNCFS UPP MBSHF GPS BO Int UZQF XF IBE
UP BTTJHO UIBU DPODSFUF UZQF UP JU
5IF ƶSTU DPNQVUBUJPO JT ƶOF CFDBVTF JU JT XJUIJO UIF SBOHF
PG WBMJE WBMVFT PG UZQF Int8 CVU UIF 127 + 1 PWFSƷPXT BOE SF
TFUT CBDL UP JUT TNBMMFTU OVNFSJD WBMVF #FDBVTF UIF NFNPSZ
UIF WBMVF JT BMMPXFE UP PDDVQZ JT ƶYFE GPS Int8 JU DBOOPU HSPX
UP BDDPNNPEBUF UIF WBMVF  UIF XBZ Integer DBO )FSF UIF
 SFQSFTFOUT IPX NBOZ CJUT UIF UZQF VTFT UP SFQSFTFOU JOUF
HSBM OVNCFST #FJOH PG B ƶYFE TJ[F DBO CF VTFGVM JO TPNF
BQQMJDBUJPOT CVU NPTU PG UIF UJNF Integer JT QSFGFSSFE

5IF SFQSFTFOUBUJPO VTFE GPS UIF ƶYFETJ[F Int UZQFT JT UXPƊT DPNQMFNFOU
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

:PV DBO ƶOE PVU UIF NJOJNVN BOE NBYJNVN CPVOET PG


OVNFSJD UZQFT VTJOH maxBound BOE minBound GSPN UIF Bounded
UZQFDMBTT )FSFƊT BO FYBNQMF VTJOH PVS Int8 BOE Int16 FYBNQMF

Prelude> import GHC.Int


Prelude> :t minBound
minBound :: Bounded a => a
Prelude> :t maxBound
maxBound :: Bounded a => a

Prelude> minBound :: Int8


-128
Prelude> minBound :: Int16
-32768
Prelude> minBound :: Int32
-2147483648
Prelude> minBound :: Int64
-9223372036854775808

Prelude> maxBound :: Int8


127
Prelude> maxBound :: Int16
32767
Prelude> maxBound :: Int32
2147483647
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

Prelude> maxBound :: Int64


9223372036854775807

5IVT ZPV DBO ƶOE UIF MJNJUBUJPOT PG QPTTJCMF WBMVFT GPS


BOZ UZQF UIBU IBT BO JOTUBODF PG UIBU QBSUJDVMBS UZQFDMBTT *O
UIJT DBTF XF BSF BCMF UP ƶOE PVU UIF SBOHF PG WBMVFT XF DBO
SFQSFTFOU XJUI BO Int8 JT  UP 
:PV DBO ƶOE PVU JG B UZQF IBT BO JOTUBODF PG Bounded PS BOZ
PUIFS UZQFDMBTT CZ BTLJOH ()$J GPS UIF :info GPS UIBU UZQF
%PJOH UIJT XJMM BMTP HJWF ZPV UIF EBUBUZQF SFQSFTFOUBUJPO GPS
UIF UZQF ZPV RVFSJFE

Prelude> :i Int
data Int = GHC.Types.I# GHC.Prim.Int#
instance Bounded Int -- Defined in ‘GHC.Enum’

Int PG DPVSTF IBT NBOZ NPSF UZQFDMBTT JOTUBODFT CVU Bounded


JT UIF POF XF DBSFE BCPVU BU UIJT UJNF

'SBDUJPOBM OVNCFST
5IF GPVS DPNNPO Fractional UZQFT JO VTF JO )BTLFMM BSF Float
Double Rational BOE Scientific Rational Double BOE Float DPNF
XJUI ZPVS JOTUBMM PG ()$ Scientific DPNFT GSPN B MJCSBSZ BT
XF NFOUJPOFE QSFWJPVTMZ Rational BOE Scientific BSF BSCJUSBSZ
QSFDJTJPO XJUI UIF MBUUFS CFJOH NVDI NPSF FƸDJFOU "SCJUSBSZ
QSFDJTJPO NFBOT UIBU UIFTF DBO CF VTFE UP EP DBMDVMBUJPOT SF
RVJSJOH B IJHI EFHSFF PG QSFDJTJPO SBUIFS UIBO CFJOH MJNJUFE
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

UP B TQFDJƶD EFHSFF PG QSFDJTJPO UIF XBZ Float BOE Double BSF


:PV BMNPTU OFWFS XBOU B Float VOMFTT ZPVƊSF EPJOH HSBQIJDT
QSPHSBNNJOH TVDI BT XJUI 0QFO(-
4PNF DPNQVUBUJPOT JOWPMWJOH OVNCFST XJMM CF GSBDUJPOBM
SBUIFS UIBO JOUFHSBM " HPPE FYBNQMF PG UIJT JT UIF EJWJTJPO
GVODUJPO (/) XIJDI IBT UIF UZQF

Prelude> :t (/)
(/) :: Fractional a => a -> a -> a

5IF OPUBUJPO Fractional a => EFOPUFT B UZQFDMBTT DPOTUSBJOU


:PV DBO SFBE JU BT ƌUIF UZQF WBSJBCMF Ԑ NVTU JNQMFNFOU UIF
Fractional UZQFDMBTTƍ 5IJT UFMMT VT UIBU XIBUFWFS UZQF PG OVN
CFS Ԑ UVSOT PVU UP CF JU NVTU CF B UZQF UIBU IBT BO JOTUBODF PG
UIF Fractional UZQFDMBTT UIBU JT UIFSF NVTU CF B EFDMBSBUJPO
PG IPX UIF PQFSBUJPOT GSPN UIBU UZQFDMBTT XJMM XPSL GPS UIF
UZQF 5IF / GVODUJPO XJMM UBLF POF OVNCFS UIBU JNQMFNFOUT
Fractional EJWJEF JU CZ BOPUIFS PG UIF TBNF UZQF BOE SFUVSO B
WBMVF PG UIF TBNF UZQF BT UIF SFTVMU
Fractional JT B UZQFDMBTT UIBU SFRVJSFT UZQFT UP BMSFBEZ IBWF
BO JOTUBODF PG UIF Num UZQFDMBTT 8F EFTDSJCF UIJT SFMBUJPO
TIJQ CFUXFFO UZQFDMBTTFT CZ TBZJOH UIBU Num JT B TVQFSDMBTT PG
Fractional 4P (+) BOE PUIFS GVODUJPOT GSPN UIF Num UZQFDMBTT
DBO CF VTFE XJUI Fractional OVNCFST CVU GVODUJPOT GSPN UIF
Fractional UZQFDMBTT DBOOPU CF VTFE XJUI BMM UZQFT UIBU IBWF B
Num JOTUBODF
)FSFƊT XIBU IBQQFOT XIFO XF VTF (/) JO UIF 3&1-
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

Prelude> 1 / 2
0.5
Prelude> 4 / 2
2.0

/PUF UIBU FWFO XIFO XF IBE B XIPMF OVNCFS BT B SFTVMU


UIF OVNCFS XBT QSJOUFE BT 2.0 EFTQJUF IBWJOH OP GSBDUJPOBM
DPNQPOFOU 5IJT JT CFDBVTF WBMVFT PG Fractional a => a EFGBVMU
UP UIF ƷPBUJOH QPJOU UZQF Double *O NPTU DBTFT ZPV XPOƊU XBOU
UP FYQMJDJUMZ VTF Double :PVƊSF VTVBMMZ CFUUFS PƵ VTJOH UIF
BSCJUSBSZ QSFDJTJPO TJCMJOH UP Integer Scientific .PTU QFPQMF
EP OPU ƶOE JU FBTZ UP SFBTPO BCPVU ƷPBUJOH QPJOU BSJUINFUJD
BOE ƶOE JU EJƸDVMU UP DPEF BSPVOE UIF RVJSLT UIPTF RVJSLT
FYJTU CZ EFTJHO CVU UIBUƊT BOPUIFS TUPSZ
TP JO PSEFS UP BWPJE
NBLJOH NJTUBLFT VTF BSCJUSBSZQSFDJTJPO UZQFT BT B NBUUFS PG
DPVSTF

 $PNQBSJOH WBMVFT


6Q UP UIJT QPJOU NPTU PG PVS PQFSBUJPOT XJUI OVNCFST IBWF
JOWPMWFE EPJOH TJNQMF BSJUINFUJD 8F DBO BMTP DPNQBSF OVN
CFST UP EFUFSNJOF XIFUIFS UIFZ BSF FRVBM HSFBUFS UIBO PS MFTT
UIBO

Prelude> let x = 5
Prelude> x == 5
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

True
Prelude> x == 6
False
Prelude> x < 7
True
Prelude> x > 3
True
Prelude> x /= 5
False

/PUJDF IFSF UIBU XF ƶSTU EFDMBSFE B WBMVF GPS ԧ VTJOH UIF


TUBOEBSE FRVBMT TJHO /PX XF LOPX UIBU GPS UIF SFNBJOEFS PG
PVS 3&1- TFTTJPO BMM JOTUBODFT PG ԧ XJMM CF UIF WBMVF  #FDBVTF
UIF FRVBMT TJHO JO )BTLFMM JT BMSFBEZ VTFE UP EFƶOF WBSJBCMFT
BOE GVODUJPOT XF NVTU VTF B EPVCMF FRVBMT TJHO == UP IBWF
UIF TQFDJƶD NFBOJOH ƌJT FRVBM UPƍ 5IF /= TZNCPM NFBOT ƌJT
OPU FRVBM UPƍ 5IF PUIFS TZNCPMT TIPVME BMSFBEZ CF GBNJMJBS UP
ZPV
)BWJOH EPOF UIJT XF TFF UIBU ()$J JT SFUVSOJOH B SFTVMU PG
FJUIFS True PS False EFQFOEJOH PO XIFUIFS UIF FYQSFTTJPO JT
USVF PS GBMTF True BOE False BSF UIF EBUB DPOTUSVDUPST GPS UIF
Bool EBUBUZQF XF TBX BCPWF *G ZPV MPPL BU UIF UZQF JOGPSNBUJPO
GPS BOZ PG UIFTF JOƶY PQFSBUPST ZPVƊMM ƶOE UIF SFTVMU UZQF MJTUFE
BT Bool

Prelude> :t (==)
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

(==) :: Eq a => a -> a -> Bool


Prelude> :t (<)
(<) :: Ord a => a -> a -> Bool

/PUJDF UIBU XF HFU TPNF UZQFDMBTT DPOTUSBJOUT BHBJO Eq JT B


UZQFDMBTT UIBU JODMVEFT FWFSZUIJOH UIBU DBO CF DPNQBSFE BOE
EFUFSNJOFE UP CF FRVBM JO WBMVF Ord JT B UZQFDMBTT UIBU JODMVEFT
BMM UIJOHT UIBU DBO CF PSEFSFE /PUF UIBU OFJUIFS PG UIFTF JT
MJNJUFE UP OVNCFST /VNCFST DBO CF DPNQBSFE BOE PSEFSFE
PG DPVSTF CVU TP DBO MFUUFST TP UIJT UZQFDMBTT DPOTUSBJOU BMMPXT
GPS ƷFYJCJMJUZ 5IFTF FRVBMJUZ BOE DPNQBSJTPO GVODUJPOT DBO
UBLF BOZ WBMVFT UIBU DBO CF TBJE UP IBWF FRVBM WBMVF PS DBO CF
PSEFSFE 5IF SFTU PG UIF UZQF JOGPSNBUJPO UFMMT VT UIBU JU UBLFT
POF PG UIFTF WBMVFT DPNQBSFT JU UP BOPUIFS WBMVF PG UIF TBNF
UZQF BOE SFUVSOT B Bool WBMVF "T XFƊWF BMSFBEZ TFFO UIF Bool
WBMVFT BSF True PS False
8JUI UIJT JOGPSNBUJPO MFUƊT USZ QMBZJOH XJUI TPNF PUIFS
WBMVFT

Prelude> 'a' == 'a'


True
Prelude> 'a' == 'b'
False
Prelude> 'a' < 'b'
True
Prelude> 'a' > 'b'
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

False
Prelude> 'a' == 'A'
False
Prelude> "Julie" == "Chris"
False

5IFTF FYBNQMFT BSF FBTZ FOPVHI UP VOEFSTUBOE 8F LOPX


UIBU BMQIBCFUJDBM DIBSBDUFST DBO CF PSEFSFE BMUIPVHI XF EP
OPU OPSNBMMZ UIJOL PG ƉBƊ BT CFJOH ƌMFTT UIBOƍ ƉCƊ #VU XF DBO
VOEFSTUBOE UIBU IFSF JU NFBOT ƊBƊ DPNFT CFGPSF ƊCƊ JO BMQIBCFUJDBM
PSEFS 'VSUIFS XF TFF UIJT BMTP XPSLT XJUI TUSJOHT TVDI BT
ƌ+VMJFƍ PS ƌ$ISJTƍ ()$J IBT GBJUIGVMMZ EFUFSNJOFE UIBU UIPTF
UXP TUSJOHT BSF OPU FRVBM JO WBMVF
/PX VTF ZPVS 3&1- UP EFUFSNJOF XIFUIFS ƉBƊ PS Ɖ"Ɗ JT HSFBUFS
/FYU UBLF B MPPL BU UIJT TBNQMF BOE TFF JG ZPV DBO ƶHVSF PVU
XIZ ()$J SFUVSOT UIF HJWFO SFTVMUT

Prelude> "Julie" > "Chris"


True
Prelude> "Chris" > "Julie"
False

(PPE UP TFF )BTLFMM DPEF UIBU SFƷFDUT SFBMJUZ ƌ+VMJFƍ JT


HSFBUFS UIBO ƌ$ISJTƍ CFDBVTF + > $ JG UIF XPSET IBE CFFO ƌ#BDLƍ
BOE ƌ#SBDLƍ UIFO JU XPVMEƊWF TLJQQFE UIF ƶSTU MFUUFS UP EFUFS
NJOF XIJDI XBT HSFBUFS CFDBVTF #  # UIFO ƍ#SBDLƍ XPVMEƊWF
CFFO HSFBUFS CFDBVTF ƉSƊ > ƉBƊ JO UIF MFYJDPHSBQIJD PSEFSJOH
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

)BTLFMM VTFT GPS DIBSBDUFST /PUF UIBU UIJT JT MFBOJOH PO UIF


Ord UZQFDMBTT JOTUBODFT GPS MJTU BOE Char :PV DBO POMZ DPNQBSF
MJTUT PG JUFNT XIFSF UIF JUFNT UIFNTFMWFT BMTP IBWF BO JOTUBODF
PG Ord "DDPSEJOHMZ UIF GPMMPXJOH XJMM XPSL CFDBVTF Char BOE
Integer IBWF JOTUBODFT PG Ord

Prelude> ['a', 'b'] > ['b', 'a']


False
Prelude> 1 > 2
False
Prelude> [1, 2] > [2, 1]
False

" EBUBUZQF UIBU IBT OP JOTUBODF PG Ord XJMM OPU XPSL XJUI
UIFTF GVODUJPOT

Prelude> data Mood = Blah | Woot deriving Show


Prelude> [Blah, Woot]
[Blah,Woot]
Prelude> [Blah, Woot] > [Woot, Blah]

<interactive>:28:14:
No instance for (Ord Mood) arising
from a use of ‘>’
In the expression: [Blah, Woot] > [Woot, Blah]
In an equation for ‘it’:
it = [Blah, Woot] > [Woot, Blah]
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

ƌ/P JOTUBODF GPS (Ord Mood)ƍ NFBOT JU EPFTOƊU IBWF BO Ord


JOTUBODF UP LOPX IPX UP PSEFS UIFTF WBMVFT
)FSF JT BOPUIFS UIJOH UIBU EPFTOƊU XPSL XJUI UIFTF GVODUJPOT

Prelude> "Julie" == 8

<interactive>:38:12:
No instance for (Num [Char]) arising from
the literal ‘8’

In the second argument of ‘(==)’, namely ‘8’


In the expression: "Julie" == 8
In an equation for ‘it’: it = "Julie" == 8

8F TBJE BCPWF UIBU DPNQBSJTPO GVODUJPOT BSF QPMZNPSQIJD


BOE DBO XPSL XJUI B MPU PG EJƵFSFOU UZQFT #VU XF BMTP OPUFE
UIBU UIF UZQF JOGPSNBUJPO POMZ BENJUUFE WBMVFT PG NBUDIJOH
UZQFT 0ODF ZPVƊWF HJWFO B UFSNMFWFM WBMVF UIBU JT B TUSJOH
TVDI BT ƌ+VMJF ƍ UIF UZQF JT EFUFSNJOFE BOE UIF PUIFS BSHVNFOU
NVTU IBWF UIF TBNF UZQF 5IF FSSPS NFTTBHF XF TFF BCPWF JT
UFMMJOH VT UIBU UIF UZQF PG UIF MJUFSBM WBMVF ƉƊ EPFTOƊU NBUDI UIF
UZQF PG UIF ƶSTU WBMVF BOE GPS UIJT GVODUJPO JU NVTU

 (P PO BOE #PPM NF


*O )BTLFMM UIF Bool EBUBUZQF DPNFT TUBOEBSE JO UIF 1SFMVEF "T
XF TBX FBSMJFS Bool JT B TVN UZQF XJUI UXP DPOTUSVDUPST
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

data Bool = False | True

5IJT EFDMBSBUJPO DSFBUFT B EBUBUZQF XJUI UIF UZQF DPOTUSVD


UPS Bool BOE XF SFGFS UP TQFDJƶD UZQFT CZ UIFJS UZQF DPOTUSVD
UPST 8F VTF UZQF DPOTUSVDUPST JO UZQF TJHOBUVSFT OPU JO UIF
FYQSFTTJPOT UIBU NBLF VQ PVS UFSNMFWFM DPEF 5IF UZQF DPO
TUSVDUPS Bool UBLFT OP BSHVNFOUT TPNF UZQF DPOTUSVDUPST EP
UBLF BSHVNFOUT
 5IF EFƶOJUJPO PG Bool BCPWF BMTP DSFBUFT UXP
EBUB DPOTUSVDUPST True BOE False #PUI PG UIFTF WBMVFT BSF PG
UZQF Bool "OZ GVODUJPO UIBU BDDFQUT WBMVFT PG UZQF #PPM NVTU
BMMPX GPS UIF QPTTJCJMJUZ PG True PS False ZPV DBOOPU TQFDJGZ
JO UIF UZQF UIBU JU TIPVME POMZ BDDFQU POF TQFDJƶD WBMVF "O
&OHMJTI MBOHVBHF GPSNVMBUJPO PG UIJT EBUBUZQF XPVME CF TPNF
UIJOH MJLF ƌ5IF EBUBUZQF Bool JT SFQSFTFOUFE CZ UIF WBMVFT
5SVF PS 'BMTFƍ
3FNFNCFS ZPV DBO ƶOE UIF UZQF PG BOZ WBMVF CZ BTLJOH
GPS JU JO ()$J KVTU BT ZPV DBO XJUI GVODUJPOT

Prelude> :t True
True :: Bool
Prelude> :t "Julie"
"Julie" :: [Char]

/PX MFUƊT IBWF TPNF GVO XJUI Bool 8FƊMM TUBSU CZ SFWJFXJOH
UIF not GVODUJPO

Prelude> :t not
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

not :: Bool -> Bool


Prelude> not True
False

/PUF UIBU XF DBQJUBMJ[F True BOE False CFDBVTF UIFZ BSF PVS
EBUB DPOTUSVDUPST 8IBU IBQQFOT JG ZPV USZ UP VTF not XJUIPVU
DBQJUBMJ[JOH UIFN
-FUƊT USZ TPNFUIJOH TMJHIUMZ NPSF DPNQMFY

Prelude> let x = 5
Prelude> not (x == 5)
False
Prelude> not (x > 7)
True

8F LOPX UIBU DPNQBSJTPO GVODUJPOT FWBMVBUF UP B Bool WBMVF


TP XF DBO VTF UIFN XJUI not
-FUƊT QMBZ XJUI JOƶY PQFSBUPST UIBU EFBM EJSFDUMZ XJUI CPPMFBO
MPHJD )PX EP XF VTF Bool BOE UIFTF BTTPDJBUFE GVODUJPOT

-- && is conjunction, so
-- this means "true and true."
Prelude> True && True
True
-- || is disjunction, so
-- this means "false or true."
Prelude> False || True
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

True
Prelude> True && False
False
Prelude> not True
False
Prelude> not (True && True)
False

8F DBO MPPL VQ JOGP BCPVU EBUBUZQFT UIBU BSF JO TDPQF JG


UIFZƊSF OPU JO TDPQF XF IBWF UP JNQPSU UIF NPEVMF UIFZ MJWF
JO UP CSJOH UIFN JOUP TDPQF
VTJOH UIF :info DPNNBOE ()$J
QSPWJEFT 4DPQF JT B XBZ UP SFGFS UP XIFSF B OBNFE CJOEJOH UP
BO FYQSFTTJPO JT WBMJE 8IFO XF TBZ TPNFUIJOH JT ƌJO TDPQFƍ JU
NFBOT ZPV DBO VTF UIBU FYQSFTTJPO CZ JUT CPVOE OBNF FJUIFS
CFDBVTF JU XBT EFƶOFE JO UIF TBNF GVODUJPO PS NPEVMF PS
CFDBVTF ZPV JNQPSUFE JU 4P JUƊT WJTJCMF UP UIF QSPHSBN XFƊSF
USZJOH UP SVO SJHIU OPX 8IBU JT CVJMU JOUP )BTLFMMƊT Prelude
NPEVMF JT TJHOJƶDBOU CFDBVTF FWFSZUIJOH JO JU JT BVUPNBUJDBMMZ
JNQPSUFE BOE JO TDPQF 8F XJMM EFNPOTUSBUF IPX UP TIVU UIJT
PƵ MBUFS CVU GPS OPX UIJT JT XIBU ZPV XBOU

&YFSDJTFT 'JOE UIF .JTUBLFT


5IF GPMMPXJOH MJOFT PG DPEF NBZ IBWF NJTUBLFT ƈ TPNF PG
UIFN XPOƊU DPNQJMF :PV LOPX XIBU ZPV OFFE UP EP

 not True && true


$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

 not (x = 6)

 (1 * 2) > 5

 [Merry] > [Happy]

 [1, 2, 3] ++ "look at me!"

$POEJUJPOBMT XJUI JGUIFOFMTF


)BTLFMM EPFTOƊU IBWF ƉJGƊ TUBUFNFOUT CVU JU EPFT IBWF JG FY
QSFTTJPOT *UƊT B CVJMUJO CJU PG TZOUBY UIBU XPSLT XJUI UIF Bool
EBUBUZQF

Prelude> if True then "Truthin'" else "Falsin'"


"Truthin'"
Prelude> if False then "Truthin'" else "Falsin'"
"Falsin'"
Prelude> :t if True then "Truthin'" else "Falsin'"
if True then "Truthin'" else "Falsin'" :: [Char]

5IF TUSVDUVSF IFSF JT

if CONDITION
then EXPRESSION\_A
else EXPRESSION\_B

*G UIF DPOEJUJPO XIJDI NVTU FWBMVBUF UP Bool


SFEVDFT UP
UIF #PPM WBMVF True UIFO EXPRESSION_A JT UIF SFTVMU PUIFSXJTF
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

EXPRESSION_B )FSF UIF UZQF XBT String BLB [Char]


CFDBVTF
UIBUƊT UIF UZQF PG UIF WBMVF UIBU JT SFUVSOFE BT B SFTVMU
*GFYQSFTTJPOT DBO CF UIPVHIU PG BT B XBZ UP DIPPTF CFUXFFO
UXP WBMVFT :PV DBO FNCFE B WBSJFUZ PG FYQSFTTJPOT XJUIJO
UIF if PG BO JGUIFOFMTF BT MPOH BT JU FWBMVBUFT UP Bool 5IF
UZQFT PG UIF FYQSFTTJPOT JO UIF then BOE else DMBVTFT NVTU CF
UIF TBNF BT JO UIF GPMMPXJOH

Prelude> let x = 0
Prelude> if (x + 1 == 1) then "AWESOME" else "wut"
"AWESOME"

)FSFƊT IPX JU SFEVDFT


$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

-- Given:
x = 0

if (x + 1 == 1) then "AWESOME" else "wut"


-- x is zero

if (0 + 1 == 1) then "AWESOME" else "wut"


-- reduce 0 + 1 so we can see if it's equal to 1

if (1 == 1) then "AWESOME" else "wut"


-- Does 1 equal 1?

if True then "AWESOME" else "wut"


-- pick the branch based on the Bool value

"AWESOME"
-- dunzo

#VU UIJT EPFT OPU XPSL

Prelude> let x = 0
Prelude> if x * 100 then "adopt a dog" else "or a cat"

<interactive>:15:7:
No instance for (Num Bool) arising
from a use of ‘*’
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

In the expression: (x * 100)


In the expression:
if (x * 100)
then "adopt a dog"
else "or a cat"
In an equation for ‘it’:
it = if (x * 100)
then "adopt a dog"
else "or a cat"

8F HPU UIJT UZQF FSSPS CFDBVTF UIF DPOEJUJPO QBTTFE UP UIF


if FYQSFTTJPO JT PG UZQF Num a => a OPU Bool BOE Bool EPFTOƊU
JNQMFNFOU UIF Num UZQFDMBTT 5P PWFSTJNQMJGZ (x * 100) FWBMV
BUFT UP B OVNFSJD SFTVMU BOE OVNCFST BSFOƊU USVUI WBMVFT *U
XPVME IBWF UZQFDIFDLFE IBE UIF DPOEJUJPO CFFO x * 100 == 0
PS x * 100 == 9001 *O UIPTF DBTFT JU XPVMEƊWF CFFO BO FRVBMJUZ
DIFDL PG UXP OVNCFST XIJDI SFEVDFT UP B #PPM WBMVF
)FSFƊT BO FYBNQMF PG B GVODUJPO UIBU VTFT B Bool WBMVF JO BO
JG FYQSFTTJPO
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

-- greetIfCool1.hs
module GreetIfCool1 where

greetIfCool :: String -> IO ()


greetIfCool coolness =
if cool
then putStrLn "eyyyyy. What's shakin'?"
else
putStrLn "pshhhh."
where cool = coolness == "downright frosty yo"

8IFO ZPV UFTU UIJT JO UIF 3&1- JU TIPVME QMBZ PVU MJLF UIJT

Prelude> :l greetIfCool1.hs
[1 of 1] Compiling GreetIfCool1
Ok, modules loaded: GreetIfCool1.
Prelude> greetIfCool "downright frosty yo"
eyyyyy. What's shakin'?
Prelude> greetIfCool "please love me"
pshhhh.

"MTP OPUF UIBU greetIfCool DPVMEƊWF CFFO XSJUUFO XJUI cool


CFJOH B GVODUJPO SBUIFS UIBO B WBMVF EFƶOFE BHBJOTU UIF BSHV
NFOU EJSFDUMZ MJLF TP
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

-- greetIfCool2.hs
module GreetIfCool2 where

greetIfCool :: String -> IO ()


greetIfCool coolness =
if cool coolness
then putStrLn "eyyyyy. What's shakin'?"
else
putStrLn "pshhhh."
where cool v = v == "downright frosty yo"

 5VQMFT
5IF UVQMF JO )BTLFMM JT B UZQF UIBU BMMPXT ZPV UP TUPSF BOE QBTT
BSPVOE NVMUJQMF WBMVFT XJUIJO B TJOHMF WBMVF 5VQMFT IBWF B
EJTUJODUJWF CVJMUJO TZOUBY UIBU JT VTFE BU CPUI UZQF BOE UFSN
MFWFMT BOE FBDI UVQMF IBT B ƶYFE OVNCFS PG DPOTUJUVFOUT 8F
SFGFS UP UVQMFT CZ IPX NBOZ DPOTUJUVFOUT BSF JO FBDI UVQMF UIF
UXPUVQMF PS QBJS GPS FYBNQMF IBT UXP WBMVFT JOTJEF JU (x, y)
UIF UISFFUVQMF PS USJQMF IBT UISFF (x, y, z) BOE TP PO 5IJT
OVNCFS JT BMTP LOPXO BT UIF UVQMFƊT BSJUZ "T XF XJMM TFF UIF
WBMVFT XJUIJO B UVQMF EP OPU IBWF UP CF PG UIF TBNF UZQF
8F XJMM TUBSU CZ MPPLJOH BU UIF UXPUVQMF B UVQMF XJUI UXP
DPOTUJUVFOUT 5IF UXPUVQMF JT FYQSFTTFE BU CPUI UIF UZQF MFWFM
BOE UFSN MFWFM XJUI UIF DPOTUSVDUPS (,) 5IF EBUBUZQF EFDMBSB
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

UJPO MPPLT MJLF UIJT

Prelude> :info (,)


data (,) a b = (,) a b

5IJT JT EJƵFSFOU GSPN UIF Bool UZQF XF MPPLFE BU FBSMJFS JO B


DPVQMF PG JNQPSUBOU XBZT FWFO BQBSU GSPN UIBU TQFDJBM UZQF
DPOTUSVDUPS TZOUBY 5IF ƶSTU JT UIBU JU IBT UXP QBSBNFUFST
SFQSFTFOUFE CZ UIF UZQF WBSJBCMFT Ԑ BOE ԑ 5IPTF IBWF UP CF
BQQMJFE UP DPODSFUF UZQFT NVDI BT WBSJBCMFT BU UIF UFSN MFWFM
IBWF UP CF BQQMJFE UP WBMVFT UP FWBMVBUF B GVODUJPO 5IF TFDPOE
NBKPS EJƵFSFODF JT UIBU UIJT JT B QSPEVDU UZQF OPU B TVN UZQF
" QSPEVDU UZQF SFQSFTFOUT B MPHJDBM DPOKVODUJPO ZPV NVTU
TVQQMZ CPUI BSHVNFOUT UP QSPEVDF B WBMVF
/PUJDF UIBU UIF UXP UZQF WBSJBCMFT BSF EJƵFSFOU TP UIBU BM
MPXT GPS UVQMFT UIBU DPOUBJO WBMVFT PG UXP EJƵFSFOU UZQFT 5IF
UZQFT BSF OPU IPXFWFS SFRVJSFE UP CF EJƵFSFOU

λ> (,) 8 10
(8,10)
λ> (,) 8 "Julie"
(8,"Julie")
λ> (,) True 'c'
(True,'c')

#VU JG XF USZ UP BQQMZ JU UP POMZ POF BSHVNFOU


$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

λ> (,) 9

<interactive>:34:1:
No instance for (Show (b0 -> (a0, b0)))
(maybe you haven't applied enough arguments to a function?)
arising from a use of ‘print’
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it

8FMM MPPL BU UIBU FSSPS 5IJT JT POF XF XJMM FYQMPSF JO EFUBJM


TPPO CVU GPS OPX UIF JNQPSUBOU QBSU JT UIF QBSU JO QBSFOUIF
TFT XF IBWFOƊU BQQMJFE UIF GVODUJPO ƈ JO UIJT DBTF UIF EBUB
DPOTUSVDUPS ƈ FOPVHI BSHVNFOUT
5IF UXPUVQMF JO )BTLFMM IBT TPNF EFGBVMU DPOWFOJFODF
GVODUJPOT GPS HFUUJOH UIF ƶSTU PS TFDPOE WBMVF 5IFZƊSF OBNFE
fst BOE snd

fst :: (a, b) -> a


snd :: (a, b) -> b

"T ZPV DBO TFF GSPN UIF BCPWF UZQFT UIFSFƊT OPUIJOH UIPTF
GVODUJPOT DPVME EP PUIFS UIBO SFUVSO UIF ƶSTU PS TFDPOE WBMVF
SFTQFDUJWFMZ
)FSF BSF TPNF FYBNQMFT PG NBOJQVMBUJOH UVQMFT TQFDJƶDBMMZ
UIF UXPUVQMF

Prelude> let myTup = (1 :: Integer, "blah")


$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

Prelude> :t myTup
myTup :: (Integer, [Char])
Prelude> fst myTup
1
Prelude> snd myTup
"blah"
Prelude> import Data.Tuple
Prelude> swap myTup
("blah",1)

8F IBE UP JNQPSU Data.Tuple CFDBVTF swap JTOƊU JODMVEFE JO


UIF 1SFMVEF
8F DBO BMTP DPNCJOF UVQMFT XJUI PUIFS FYQSFTTJPOT

Prelude> 2 + fst (1, 2)


3
Prelude> 2 + snd (1, 2)
4

5IF (x, y) TZOUBY PG UIF UVQMF JT TQFDJBM 5IF DPOTUSVDUPST


ZPV VTF JO UIF UZQF TJHOBUVSFT BOE JO ZPVS DPEF UFSNT
BSF
TZOUBDUJDBMMZ JEFOUJDBM FWFO UIPVHI UIFZƊSF EJƵFSFOU UIJOHT
4PNFUJNFT UIBU UZQF DPOTUSVDUPS JT SFGFSSFE UP XJUIPVU UIF
UZQF WBSJBCMFT FYQMJDJUMZ JOTJEF PG JU TVDI BT (,) 0UIFS UJNFT
ZPVƊMM TFF (a, b)  QBSUJDVMBSMZ JO UZQF TJHOBUVSFT
:PV DBO VTF UIBU TZOUBY UP QBUUFSO NBUDI
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

*UƊT HFOFSBMMZ VOXJTF UP VTF UVQMFT PG BO PWFSMZ MBSHF TJ[F


CPUI GPS FƸDJFODZ BOE TBOJUZ SFBTPOT .PTU UVQMFT ZPV TFF XJMM
CF ( , , , , ) UVQMF
PS TNBMMFS

 -JTUT
-JTUT JO )BTLFMM BSF BOPUIFS UZQF VTFE UP DPOUBJO NVMUJQMF
WBMVFT XJUIJO B TJOHMF WBMVF )PXFWFS UIFZ EJƵFS GSPN UVQMFT
JO UISFF JNQPSUBOU XBZT 'JSTU BMM DPOTUJUVFOUT PG B MJTU NVTU
CF PG UIF TBNF UZQF 4FDPOE -JTUT IBWF UIFJS PXO EJTUJODU
[] TZOUBY -JLF UIF UVQMF TZOUBY JU JT VTFE GPS CPUI UIF UZQF
DPOTUSVDUPS JO UZQF TJHOBUVSFT BOE BU UIF UFSN MFWFM UP FYQSFTT
MJTU WBMVFT 5IJSE UIF OVNCFS PG DPOTUJUVFOUT XJUIJO B MJTU DBO
DIBOHF BT ZPV PQFSBUF PO UIF MJTU VOMJLF UVQMFT XIFSF UIF BSJUZ
JT TFU JO UIF UZQF BOE JNNVUBCMF
)FSFƊT BO FYBNQMF GPS ZPVS 3&1-

Prelude> let awesome = ["Papuchon", "curry", ":)"]


Prelude> awesome
["Papuchon","curry",":)"]

Prelude> :t awesome
awesome :: [[Char]]

'JSTU UIJOH UP OPUF JT UIBU awesome JT B MJTU PG MJTUT PG Char WBMVFT


CFDBVTF JU JT B MJTU PG TUSJOHT BOE B TUSJOH JT JUTFMG KVTU B UZQF
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

BMJBT GPS [Char] 5IJT NFBOT BMM UIF GVODUJPOT BOE PQFSBUJPOT
WBMJE GPS MJTUT PG BOZ WBMVF VTVBMMZ FYQSFTTFE BT [a] BSF WBMJE
GPS String CFDBVTF [Char] JT NPSF TQFDJƶD UIBO [a]

Prelude> let alsoAwesome = ["Quake", "The Simons"]


Prelude> :t (++)
(++) :: [a] -> [a] -> [a]
Prelude> awesome ++ alsoAwesome
["Papuchon","curry",":)","Quake","The Simons"]

Prelude> let allAwesome = [awesome, alsoAwesome]


Prelude> allAwesome
[["Papuchon","curry",":)"],["Quake","The Simons"]]
Prelude> :t allAwesome
allAwesome :: [[[Char]]]
Prelude> :t concat
concat :: [[a]] -> [a]
Prelude> concat allAwesome
["Papuchon","curry",":)","Quake","The Simons"]

8FƊMM TBWF B GVMM FYQMPSBUJPO PG UIF MJTU EBUBUZQF VOUJM XF


HFU UP UIF DIBQUFS PO MJTUT 5IF MJTU EBUB TUSVDUVSF HFUT B XIPMF
DIBQUFS CFDBVTF MJTUT IBWF TPNF JOUFSFTUJOH DPNQMFYJUZ XFƊSF
HPJOH UP VTF UIFN UP EFNPOTUSBUF TPNF UIJOHT BCPVU )BTLFMMƊT
OPOTUSJDU FWBMVBUJPO BOE UIFSF BSF NBOZ TUBOEBSE GVODUJPOT
BOE DPOTUSVDUT UIBU DBO CF VTFE XJUI MJTUT
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

 $IBQUFS &YFSDJTFT


"T JO QSFWJPVT DIBQUFST ZPV XJMM HBJO NPSF CZ XPSLJOH PVU
UIF BOTXFS CFGPSF ZPV DIFDL XIBU ()$J UFMMT ZPV CVU CF TVSF
UP VTF ZPVS 3&1- UP DIFDL ZPVS BOTXFST UP UIF GPMMPXJOH FYFS
DJTFT "MTP ZPV XJMM OFFE UP IBWF UIF awesome alsoAwesome BOE
allAwesome DPEF GSPN BCPWF JO TDPQF GPS UIJT 3&1- TFTTJPO 'PS
DPOWFOJFODF PG SFGFSFODF IFSF BSF UIPTF WBMVFT BHBJO

awesome = ["Papuchon", "curry", ":)"]


alsoAwesome = ["Quake", "The Simons"]
allAwesome = [awesome, alsoAwesome]

length JT B GVODUJPO UIBU UBLFT B MJTU BOE SFUVSOT B SFTVMU UIBU


UFMMT IPX NBOZ JUFNT BSF JO UIF MJTU

 (JWFO UIF EFƶOJUJPO PG length BCPWF XIBU XPVME UIF UZQF


TJHOBUVSF CF )PX NBOZ BSHVNFOUT PG XIBU UZQF EPFT JU
UBLF 8IBU JT UIF UZQF PG UIF SFTVMU JU FWBMVBUFT UP

 8IBU BSF UIF SFTVMUT PG UIF GPMMPXJOH FYQSFTTJPOT

B
length [1, 2, 3, 4, 5]
C
length [(1, 2), (2, 3), (3, 4)]
D
length allAwesome
E
length (concat allAwesome)
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

 (JWFO XIBU XF LOPX BCPVU OVNFSJD UZQFT BOE UIF UZQF


TJHOBUVSF PG length MPPL BU UIFTF UXP FYQSFTTJPOT 0OF
XPSLT BOE POF SFUVSOT BO FSSPS %FUFSNJOF XIJDI XJMM
SFUVSO BO FSSPS BOE XIZ
OC ZPV XJMM ƶOE Foldable t => t a SFQSFTFOUJOH [a] BT
XJUI concat JO UIF QSFWJPVT DIBQUFS "HBJO DPOTJEFS Foldable
t UP SFQSFTFOU B MJTU IFSF FWFO UIPVHI MJTU JT POMZ POF PG
UIF QPTTJCMF UZQFT

Prelude> 6 / 3
-- and
Prelude> 6 / length [1, 2, 3]

 )PX DBO ZPV ƶY UIF CSPLFO DPEF GSPN UIF QSFDFEJOH


FYFSDJTF VTJOH B EJƵFSFOU EJWJTJPO GVODUJPOPQFSBUPS

 8IBU JT UIF UZQF PG UIF FYQSFTTJPO 2 + 3 == 5 8IBU XPVME


XF FYQFDU BT B SFTVMU

 8IBU JT UIF UZQF BOE FYQFDUFE SFTVMU WBMVF PG UIF GPMMPX


JOH

Prelude> let x = 5
Prelude> x + 3 == 5

 #FMPX BSF TPNF CJUT PG DPEF 8IJDI XJMM XPSL 8IZ PS


XIZ OPU *G UIFZ XJMM XPSL XIBU WBMVF XPVME UIFTF SFEVDF
UP
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

Prelude> length allAwesome == 2


Prelude> length [1, 'a', 3, 'b']
Prelude> length allAwesome + length awesome
Prelude> (8 == 8) && ('b' < 'a')
Prelude> (8 == 8) && 9

 8SJUF B GVODUJPO UIBU UFMMT ZPV XIFUIFS PS OPU B HJWFO


4USJOH PS MJTU
JT B QBMJOESPNF )FSF ZPVƊMM XBOU UP VTF B
GVODUJPO DBMMFE ƊSFWFSTF Ɗ B QSFEFƶOFE GVODUJPO UIBU EPFT
KVTU XIBU JU TPVOET MJLF

reverse :: [a] -> [a]


reverse "blah"
"halb"

isPalindrome :: (Eq a) => [a] -> Bool


isPalindrome x = undefined

 8SJUF B GVODUJPO UP SFUVSO UIF BCTPMVUF WBMVF PG B OVNCFS


VTJOH JGUIFOFMTF

myAbs :: Integer -> Integer


myAbs = undefined

 'JMM JO UIF EFƶOJUJPO PG UIF GPMMPXJOH GVODUJPO VTJOH fst


BOE snd
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

f :: (a, b) -> (c, d) -> ((b, d), (a, c))


f = undefined

$PSSFDUJOH TZOUBY
*O UIF GPMMPXJOH FYBNQMFT ZPVƊMM CF TIPXO TZOUBDUJDBMMZ JODPS
SFDU DPEF 5ZQF JU JO BOE USZ UP DPSSFDU JU JO ZPVS UFYU FEJUPS
WBMJEBUJOH JU XJUI ()$ PS ()$J

 )FSF XF XBOU B GVODUJPO UIBU BEET  UP UIF MFOHUI PG B


TUSJOH BSHVNFOU BOE SFUVSOT UIBU SFTVMU

x = (+)

F xs = w 'x' 1
where w = length xs

 5IJT JT TVQQPTFE UP CF UIF JEFOUJUZ GVODUJPO id

\ X = x

 8IFO ƶYFE UIJT GVODUJPO XJMM SFUVSO  GSPN UIF WBMVF [1,
2, 3] )JOU ZPV NBZ OFFE UP SFGFS CBDL UP UIF TFDUJPO
BCPVU WBSJBCMFT DPOWFOUJPOT JO ƌ)FMMP )BTLFMMƍ UP SFGSFTI
ZPVS NFNPSZ PG UIJT OPUBUJPO

\ x : xs -> x
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

 8IFO ƶYFE UIJT GVODUJPO XJMM SFUVSO  GSPN UIF WBMVF (1,
2)

f (a b) = A

.BUDI UIF GVODUJPO OBNFT UP UIFJS UZQFT


 8IJDI PG UIF GPMMPXJOH UZQFT JT UIF UZQF PG show

B
show a => a -> String

C
Show a -> a -> String

D
Show a => a -> String

 8IJDI PG UIF GPMMPXJOH UZQFT JT UIF UZQF PG (==)

B
a -> a -> Bool

C
Eq a => a -> a -> Bool

D
Eq a -> a -> a -> Bool

E
Eq a => A -> Bool

 8IJDI PG UIF GPMMPXJOH UZQFT JT UIF UZQF PG fst

B
(a, b) -> a

C
b -> a

D
(a, b) -> b

 8IJDI PG UIF GPMMPXJOH UZQFT JT UIF UZQF PG (+)


$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

B
(+) :: Num a -> a -> a -> Bool

C
(+) :: Num a => a -> a -> Bool

D
(+) :: num a => a -> a -> a

E
(+) :: Num a => a -> a -> a

F
(+) :: a -> a -> a

 %FƶOJUJPOT
 " UVQMF JT BO PSEFSFE HSPVQJOH PG WBMVFT *O )BTLFMM ZPV
DBOOPU IBWF B UVQMF XJUI POMZ POF FMFNFOU CVU UIFSF JT B
[FSP UVQMF BMTP DBMMFE VOJU PS () 5IF UZQFT PG UIF FMFNFOUT
PG UVQMFT BSF BMMPXFE UP WBSZ TP ZPV DBO IBWF CPUI 4USJOH
4USJOH
PS *OUFHFS 4USJOH
 5VQMFT JO )BTLFMM BSF UIF VTVBM
NFBOT PG FYQSFTTJOH BO BOPOZNPVT QSPEVDU

 " UZQFDMBTT JT B TFU PG PQFSBUJPOT EFƶOFE XJUI SFTQFDU UP


B QPMZNPSQIJD UZQF 8IFO B UZQF JT BO JOTUBODF PG B
UZQFDMBTT WBMVFT PG UIBU UZQF DBO CF VTFE JO UIF TUBOEBSE
PQFSBUJPOT EFƶOFE GPS UIBU UZQFDMBTT *O )BTLFMM UZQF
DMBTTFT BSF VOJRVF QBJSJOHT PG DMBTT BOE DPODSFUF JOTUBODF
5IJT NFBOT UIBU JG B HJWFO UZQF Ԑ IBT BO JOTUBODF PG Eq JU
IBT POMZ POF JOTUBODF PG Eq

 %BUB DPOTUSVDUPST JO )BTLFMM QSPWJEF B NFBOT PG DSFBUJOH


WBMVFT UIBU JOIBCJU B HJWFO UZQF %BUB DPOTUSVDUPST JO
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

)BTLFMM IBWF B UZQF BOE DBO FJUIFS CF DPOTUBOU WBMVFT


OVMMBSZ
PS UBLF POF PS NPSF BSHVNFOUT KVTU MJLF GVODUJPOT
*O UIF GPMMPXJOH FYBNQMF Cat JT B OVMMBSZ EBUB DPOTUSVDUPS
GPS Pet BOE Dog JT B EBUB DPOTUSVDUPS UIBU UBLFT BO BSHVNFOU

-- Why name a cat? They don't answer anyway.


type Name = String

data Pet = Cat | Dog Name

5IF EBUB DPOTUSVDUPST IBWF UIF GPMMPXJOH UZQFT

Prelude> :t Cat
Cat :: Pet
Prelude> :t Dog
Dog :: Name -> Pet

 5ZQF DPOTUSVDUPST JO )BTLFMM BSF OPU WBMVFT BOE DBO POMZ CF


VTFE JO UZQF TJHOBUVSFT +VTU BT EBUB EFDMBSBUJPOT HFOFSBUF
EBUB DPOTUSVDUPST UP DSFBUF WBMVFT UIBU JOIBCJU UIBU UZQF
EBUB EFDMBSBUJPOT HFOFSBUF UZQF DPOTUSVDUPST XIJDI DBO CF
VTFE UP EFOPUF UIBU UZQF *O UIF BCPWF FYBNQMF Pet JT UIF
UZQF DPOTUSVDUPS " HVJEFMJOF GPS EJƵFSFOUJBUJOH UIF UXP
LJOET PG DPOTUSVDUPST JT UIBU UZQF DPOTUSVDUPST BMXBZT HP
UP UIF MFǒ PG UIF = JO B EBUB EFDMBSBUJPO
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

 %BUB EFDMBSBUJPOT EFƶOF OFX EBUBUZQFT JO )BTLFMM %BUB


EFDMBSBUJPOT BMXBZT DSFBUF B OFX UZQF DPOTUSVDUPS CVU NBZ
PS NBZ OPU DSFBUF OFX EBUB DPOTUSVDUPST %BUB EFDMBSBUJPOT
BSF IPX XF SFGFS UP UIF FOUJSF EFƶOJUJPO UIBU CFHJOT XJUI
UIF data LFZXPSE

 " UZQF BMJBT JT B XBZ UP SFGFS UP B UZQF DPOTUSVDUPS PS UZQF


DPOTUBOU CZ BO BMUFSOBUF OBNF VTVBMMZ UP DPNNVOJDBUF
TPNFUIJOH NPSF TQFDJƶD PS GPS CSFWJUZ

type Name = String


-- creates a new type alias Name of the
-- type String *not* a data declaration,
-- just a type alias declaration

 "SJUZ JT UIF OVNCFS PG BSHVNFOUT B GVODUJPO BDDFQUT 5IJT


OPUJPO JT B MJUUMF TMJQQFSZ JO )BTLFMM BT EVF UP DVSSZJOH BMM
GVODUJPOT BSF BSJUZ BOE XF IBOEMF BDDFQUJOH NVMUJQMF
BSHVNFOUT CZ OFTUJOH GVODUJPOT

 1PMZNPSQIJTN JO )BTLFMM NFBOT CFJOH BCMF UP XSJUF DPEF


JO UFSNT PG WBMVFT XIJDI NBZ CF POF PG TFWFSBM PS BOZ
UZQF 1PMZNPSQIJTN JO )BTLFMM JT FJUIFS QBSBNFUSJD PS
DPOTUSBJOFE 5IF JEFOUJUZ GVODUJPO id JT BO FYBNQMF PG B
QBSBNFUSJDBMMZ QPMZNPSQIJD GVODUJPO

id :: a -> a
id x = x
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

)FSF id XPSLT GPS B WBMVF PG BOZ UZQF CFDBVTF JU EPFTOƊU


VTF BOZ JOGPSNBUJPO TQFDJƶD UP B HJWFO UZQF PS TFU PG UZQFT
8IFSFBT UIF GPMMPXJOH GVODUJPO isEqual

isEqual :: Eq a => a -> a -> Bool


isEqual x y = x == y

*T QPMZNPSQIJD CVU DPOTUSBJOFE PS CPVOEFE UP UIF TFU PG


UZQFT XIJDI IBWF BO JOTUBODF PG UIF Eq UZQFDMBTT 5IF EJG
GFSFOU LJOET PG QPMZNPSQIJTN XJMM CF EJTDVTTFE JO HSFBUFS
EFUBJM JO B MBUFS DIBQUFS

 /BNFT BOE WBSJBCMFT


/BNFT
*O )BTLFMM UIFSF BSF TFWFO DBUFHPSJFT PG FOUJUJFT UIBU IBWF
OBNFT GVODUJPOT UFSNMFWFM WBSJBCMFT EBUB DPOTUSVDUPST UZQF
WBSJBCMFT UZQF DPOTUSVDUPST UZQFDMBTTFT BOE NPEVMFT 5FSN
MFWFM WBSJBCMFT BOE EBUB DPOTUSVDUPST FYJTU JO ZPVS UFSNT 5FSN
MFWFM JT XIFSF ZPVS WBMVFT MJWF BOE JT UIF DPEF UIBU FYFDVUFT
XIFO ZPVS QSPHSBN JT SVOOJOH "U UIF UZQFMFWFM XIJDI JT
VTFE EVSJOH UIF TUBUJD BOBMZTJT  WFSJƶDBUJPO PG ZPVS QSPHSBN
XF IBWF UZQF WBSJBCMFT UZQF DPOTUSVDUPST BOE UZQFDMBTTFT
-BTUMZ GPS UIF QVSQPTF PG PSHBOJ[JOH PVS DPEF JOUP DPIFSFOU
HSPVQJOHT BDSPTT EJƵFSFOU ƶMFT NPSF MBUFS
XF IBWF NPEVMFT
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

$POWFOUJPOT GPS WBSJBCMFT


)BTLFMM VTFT B MPU PG WBSJBCMFT BOE TPNF DPOWFOUJPOT IBWF
EFWFMPQFE *UƊT OPU DSJUJDBM UIBU ZPV NFNPSJ[F UIJT CFDBVTF GPS
UIF NPTU QBSU UIFTF BSF NFSFMZ DPOWFOUJPOT CVU GBNJMJBSJ[JOH
ZPVSTFMG XJUI UIFN XJMM IFMQ ZPV SFBE )BTLFMM DPEF
5ZQF WBSJBCMFT UIBU JT WBSJBCMFT JO UZQF TJHOBUVSFT
HFOFS
BMMZ TUBSU BU Ԑ BOE HP GSPN UIFSF Ԑ ԑ Ԓ BOE TP GPSUI :PV NBZ
PDDBTJPOBMMZ TFF UIFN XJUI OVNCFST BQQFOEFE UP UIFN FH
Ԑ
'VODUJPOT DBO CF VTFE BT BSHVNFOUT BOE JO UIBU DBTF BSF
UZQJDBMMZ MBCFMFE XJUI WBSJBCMFT TUBSUJOH BU ԕ GPMMPXFE CZ Ԗ BOE
TP PO
 5IFZ NBZ TPNFUJNFT IBWF OVNCFST BQQFOEFE FH ԕ

BOE NBZ BMTP TPNFUJNFT CF EFDPSBUFE XJUI UIF ஥ DIBSBDUFS BT


JO ԕ ஥  5IJT XPVME CF QSPOPVODFE ƌFƵQSJNF ƍ TIPVME ZPV IBWF
OFFE UP TBZ JU BMPVE 6TVBMMZ UIJT EFOPUFT B GVODUJPO UIBU JT
DMPTFMZ SFMBUFE UP PS B IFMQFS GVODUJPO UP GVODUJPO ԕ 'VODUJPOT
NBZ BMTP CF HJWFO WBSJBCMF OBNFT UIBU BSF OPU PO UIJT TQFDUSVN
BT B NOFNPOJD 'PS FYBNQMF B GVODUJPO UIBU SFTVMUT JO B MJTU
PG QSJNF OVNCFST NJHIU CF DBMMFE ԟ PS B GVODUJPO UIBU GFUDIFT
TPNF UFYU NJHIU CF DBMMFE ԣԧԣ
7BSJBCMFT EP OPU IBWF UP CF B TJOHMF MFUUFS *O TNBMM QSPHSBNT
UIFZ PǒFO BSF JO MBSHFS QSPHSBNT UIFZ BSF PǒFO OPU B TJOHMF
MFUUFS *G UIFSF BSF NBOZ WBSJBCMFT JO B GVODUJPO PS QSPHSBN BT
JT DPNNPO JU JT IFMQGVM UP IBWF EFTDSJQUJWF WBSJBCMF OBNFT *U
JT PǒFO BEWJTBCMF JO EPNBJOTQFDJƶD DPEF UP UP VTF EPNBJO
$)"15&3  #&$"64& 1*(4 $"/Ɗ5 '-: 

TQFDJƶD WBSJBCMF OBNFT


"SHVNFOUT UP GVODUJPOT BSF NPTU PǒFO HJWFO OBNFT TUBSU
JOH BU ԧ BHBJO PDDBTJPOBMMZ TFFO OVNCFSFE BT JO ԧ 0UIFS
TJOHMFMFUUFS WBSJBCMF OBNFT NBZ CF DIPTFO XIFO UIFZ TFSWF B
NOFNPOJD SPMF TVDI BT DIPPTJOH ԡ UP SFQSFTFOU B WBMVF UIBU JT
UIF SBEJVT PG B DJSDMF
*G ZPV IBWF B MJTU PG UIJOHT ZPV IBWF OBNFE ԧ CZ DPOWFOUJPO
UIBU XJMM VTVBMMZ CF DBMMFE ԧԢ UIBU JT UIF QMVSBM PG ԧ :PV XJMM
TFF UIJT DPOWFOUJPO PǒFO JO UIF GPSN (x:xs) XIJDI NFBOT ZPV
IBWF B MJTU JO XIJDI UIF IFBE PG UIF MJTU JT ԧ BOE UIF SFTU PG UIF
MJTU JT ԧԢ
"MM PG UIFTF UIPVHI BSF NFSFMZ DPOWFOUJPOT OPU EFƶOJUF
SVMFT 8IJMF XF XJMM HFOFSBMMZ BEIFSF UP UIF DPOWFOUJPOT JO
UIJT CPPL BOZ )BTLFMM DPEF ZPV TFF PVU JO UIF XJME NBZ OPU
$BMMJOH B UZQF WBSJBCMF ԧ JOTUFBE PG Ԑ JT OPU HPJOH UP CSFBL
BOZUIJOH "T JO UIF MBNCEB DBMDVMVT UIF OBNFT EPOƊU IBWF BOZ
JOIFSFOU NFBOJOH 8F PƵFS UIJT JOGPSNBUJPO BT B EFTDSJQUJWF
HVJEF PG )BTLFMM DPOWFOUJPOT OPU BT SVMFT ZPV NVTU GPMMPX JO
ZPVS PXO DPEF
$IBQUFS 

5ZQFT

4IF XBT UIF TJOHMF


BSUJƶDFS PG UIF XPSME
*O XIJDI TIF TBOH "OE
XIFO TIF TBOH UIF TFB
8IBUFWFS TFMG JU IBE
CFDBNF UIF TFMG
5IBU XBT IFS TPOH GPS TIF
XBT UIF NBLFS

8BMMBDF 4UFWFOT ƌ5IF


*EFB PG 0SEFS BU ,FZ
8FTUƍ


$)"15&3  5:1&4 

 5ZQFT
*O UIF MBTU DIBQUFS XF MPPLFE BU TPNF CVJMUJO EBUBUZQFT TVDI
BT Bool BOE UVQMFT BOE XF IBE B CSJFG SVOJO XJUI UIF UZQF
DMBTTFT Num BOE Eq )PXFWFS B EFFQ VOEFSTUBOEJOH PG UZQFT
BOE IPX UP SFBE BOE JOUFSQSFU UIFN JT GVOEBNFOUBM UP SFBEJOH
BOE XSJUJOH )BTLFMM
"T XF IBWF TFFO B EBUBUZQF EFDMBSBUJPO EFƶOFT B UZQF DPO
TUSVDUPS BOE EBUB DPOTUSVDUPST %BUB DPOTUSVDUPST BSF UIF WBM
VFT PG B QBSUJDVMBS UZQF UIFZ BSF BMTP GVODUJPOT UIBU MFU VT
DSFBUF EBUB PS WBMVFT PG B QBSUJDVMBS UZQF BMUIPVHI JU XJMM
UBLF TPNF UJNF CFGPSF UIF GVMM JNQPSU PG UIJT CFDPNFT DMFBS
*O )BTLFMM ZPV DBOOPU DSFBUF VOUZQFE EBUB TP FYDFQU GPS B
TQSJOLMJOH PG TZOUBDUJD TVHBS GPS UIJOHT MJLF OVNCFST PS GVOD
UJPOT FWFSZUIJOH PSJHJOBUFT JO B EBUB DPOTUSVDUPS GSPN TPNF
EFƶOJUJPO PG B UZQF
*O UIJT DIBQUFS XFƊSF HPJOH UP UBLF B EFFQFS MPPL BU UIF UZQF
TZTUFN BOE

Ƒ MFBSO NPSF BCPVU RVFSZJOH BOE SFBEJOH UZQF TJHOBUVSFT

Ƒ TFF UIBU DVSSZJOH IBT VOGPSUVOBUFMZ OPUIJOH UP EP XJUI


GPPE

Ƒ UBLF B DMPTFS MPPL BU EJƵFSFOU LJOET PG QPMZNPSQIJTN

Ƒ MPPL BU UZQF JOGFSFODF BOE IPX UP EFDMBSF UZQFT GPS PVS


GVODUJPOT
$)"15&3  5:1&4 

 8IBU BSF UZQFT GPS


)BTLFMM JT BO JNQMFNFOUBUJPO PG B QVSF MBNCEB DBMDVMVT JO
UIF TFOTF UIBU JU JTOƊU NVDI NPSF UIBO TZOUBDUJD TVHBS PWFS UIF
CBTJD TZTUFN PG WBSJBCMFT BCTUSBDUJPOT BOE BQQMJDBUJPOT UIBU
DPOTUJUVUF UIF SVMFT PG UIF MBNCEB DBMDVMVT ƈ BU MFBTU PG B UZQFE
MBNCEB DBMDVMVT %FWFMPQNFOUT JO MPHJD NBUIFNBUJDT BOE
DPNQVUFS TDJFODF MFE UP UIF EJTDPWFSZ PS JOWFOUJPO UBLF ZPVS
QJDL
PG B UZQFE MBNCEB DBMDVMVT DBMMFE 4ZTUFN ' JO UIF T
)BTLFMM IBT JNQSPWFE PO 4ZTUFN ' JO TPNF LFZ XBZT TVDI BT
CZ BMMPXJOH HFOFSBM SFDVSTJPO NPSF PO UIBU JO B MBUFS DIBQUFS

BOE UIF )JOEMFZ.JMOFS TZTUFN UP QFSNJU UZQF JOGFSFODF NPSF


PO UIBU MBUFS JO UIJT DIBQUFS
CVU UIF DPSF MPHJD JT UIF TBNF
4P XIZ EP XF XBOU UZQFT 5ZQF TZTUFNT JO MPHJD BOE NBUI
FNBUJDT IBWF CFFO EFTJHOFE UP JNQPTF DPOTUSBJOUT UIBU FOGPSDF
DPSSFDUOFTT 'PS PVS QVSQPTFT XF DBO TBZ UIBU XFMMEFTJHOFE
UZQF TZTUFNT IFMQ FMJNJOBUF TPNF DMBTTFT PG FSSPST BT XFMM BT
DPODFSOT TVDI BT XIBU UIF FƵFDU PG B DPOEJUJPOBM PWFS B OPO
#PPMFBO WBMVF NJHIU CF " UZQF TZTUFN EFƶOFT UIF BTTPDJBUJPOT
CFUXFFO EJƵFSFOU QBSUT PG B QSPHSBN BOE DIFDLT UIBU BMM UIF
QBSUT ƶU UPHFUIFS JO B MPHJDBMMZ DPOTJTUFOU QSPWBCMZ DPSSFDU
XBZ
-FUƊT DPOTJEFS B TIPSU TPNFXIBU PWFSTJNQMJƶFE FYBNQMF
5IF Bool UZQF JT B TFU XJUI UXP JOIBCJUBOUT True BOE False BT
XF TBX JO UIF MBTU DIBQUFS "OZUJNF UIF WBMVF True PS False
PDDVST JO B )BTLFMM QSPHSBN UIF UZQFDIFDLFS XJMM LOPX UIFZƊSF
$)"15&3  5:1&4 

NFNCFST PG UIF Bool UZQF 5IF JOWFSTF JT UIBU XIFOFWFS UIF


UZQF Bool JT EFDMBSFE JO B UZQF TJHOBUVSF UIF DPNQJMFS XJMM
FYQFDU POF PG UIPTF UXP WBMVFT BOE POMZ POF PG UIPTF UXP
WBMVFT ZPV HFU B UZQF FSSPS JG ZPV USZ UP QBTT B OVNCFS XIFSF
B Bool JT FYQFDUFE
*O )BTLFMM XIFSF UZQJOH JT TUBUJD UZQFDIFDLJOH PDDVST BU
DPNQJMF UJNF 5IBU NFBOT NBOZ FSSPST XJMM CF DBVHIU CFGPSF
ZPV USZ UP FYFDVUF PS SVO ZPVS QSPHSBN 5IF EJƵFSFODF JTOƊU
BMXBZT PCWJPVT CFDBVTF ()$J BMMPXT ZPV UP UZQFDIFDL UIJOHT
JOUFSBDUJWFMZ BT ZPVƊSF XSJUJOH UIFN BT XFMM BT FYFDVUF UIFN JG
UIFZ UZQFDIFDL /P UZQF TZTUFN DBO FMJNJOBUF BMM QPTTJCJMJUJFT
GPS FSSPS TP UIF QPTTJCJMJUZ PG SVOUJNF FSSPST BOE FYDFQUJPOT
TUJMM FYJTUT BOE UFTUJOH UP XIJDI XF EFWPUF BO FOUJSF MBUFS
DIBQUFS
PG QSPHSBNT JT TUJMM OFDFTTBSZ CVU UIF UZQF TZTUFN
DVUT EPXO PO JU B HSFBU EFBM
(PPE UZQF TZTUFNT DBO BMTP FOBCMF DPNQJMFS PQUJNJ[BUJPOT
CFDBVTF UIF DPNQJMFS DBO LOPX BOE QSFEJDU DFSUBJO UIJOHT
BCPVU UIF FYFDVUJPO PG B QSPHSBN CBTFE PO UIF UZQFT 5ZQFT
DBO BMTP TFSWF BT EPDVNFOUBUJPO PG ZPVS QSPHSBN XIJDI JT
XIZ XF FODPVSBHF ZPV UP EFDMBSF UZQFT UIBU JT XSJUF UIF UZQF
TJHOBUVSFT
GPS ZPVS GVODUJPOT *U XPOƊU NBUUFS UPP NVDI XIFO
ZPVƊSF XSJUJOH TNBMM QSPHSBNT CVU BT QSPHSBNT HFU MPOHFS
UZQF TJHOBUVSFT BMPOF DBO IFMQ ZPV SFBE ZPVS QSPHSBN BOE
SFNFNCFS XIBU ZPV XFSF EPJOH BOE IFMQ BOZPOF FMTF XIP
NJHIU CF USZJOH UP VTF ZPVS DPEF BT XFMM *G UIJT QBSBHSBQI
EJEOƊU NBLF TFOTF UP ZPV OPX UIBUƊT ƶOF ƈ XFƊMM SFUVSO UP
$)"15&3  5:1&4 

UIFTF QPJOUT BU TFWFSBM QPJOUT MBUFS JO UIF CPPL


:PV NBZ GFFM UIBU )BTLFMMƊT UZQF TZTUFN SFRVJSFT B MPU PG VQ
GSPOU XPSL 5IJT VQGSPOU DPTU DPNFT XJUI B MBUFS QBZPƵ DPEF
UIBU JT TBGFS BOE EPXO UIF MJOF FBTJFS UP NBJOUBJO 8PSLJOH
XJUI B HPPE UZQF TZTUFN DBO FMJNJOBUF UIPTF UFTUT UIBU POMZ
DIFDL UIBU ZPVƊSF QBTTJOH UIF SJHIU TPSU PG EBUB BSPVOE BOE
TJODF UFTUT BSF NPSF DPEF UIBU ZPV IBWF UP XSJUF DPSSFDUMZ
BOE
NBJOUBJO JU XJMM FWFOUVBMMZ TBWF ZPV UJNF BOE FƵPSU
.BOZ QFSIBQT NPTU QSPHSBNNJOH MBOHVBHFT IBWF UZQF
TZTUFNT UIBU GFFM MJLF IBHHMJOH XJUI B QFUUZ NFSDIBOU )PXFWFS
XF CFMJFWF )BTLFMM QSPWJEFT B UZQF TZTUFN UIBU NPSF DMPTFMZ
SFTFNCMFT B RVJFU QMFBTBOU DPOWFSTBUJPO XJUI B DPMMFBHVF UIBO
BO BSHVNFOU JO UIF CB[BBS .VDI PG XIBU XF TVHHFTU XJUI
SFHBSET UP QVUUJOH DPEF JO B ƶMF MPBEJOH JU JO B 3&1- RVFSZJOH
UZQFT JO UIF 3&1- BOE TP GPSUI JT BCPVU DSFBUJOH IBCJUT DPO
EVDJWF UP IBWJOH UIJT QMFBTBOU CBDL BOE GPSUI XJUI ZPVS UZQF
TZTUFN

 )PX UP SFBE UZQF TJHOBUVSFT


*O QSFWJPVT DIBQUFST XFƊWF TFFO UIBU XF DBO RVFSZ UZQFT JO UIF
3&1- CZ VTF PG UIF :type PS :t DPNNBOE :PV DBO RVFSZ UZQFT
GPS GVODUJPOT QBSUJBMMZ BQQMJFE GVODUJPOT BOE WBMVFT XIJDI
BSF JO B XBZ GVMMZ BQQMJFE GVODUJPOT
8IFO XF RVFSZ UIF UZQFT PG WBMVFT XF TFF TPNFUIJOH MJLF
UIJT
$)"15&3  5:1&4 

Prelude> :type 't'


't' :: Char -- 't' has the type Char
Prelude> :type "julie"
"julie" :: [Char] -- "julie" has the type String
Prelude> :type True
True :: Bool -- True has the type Bool

8IFO XF RVFSZ UIF UZQFT PG OVNFSJD WBMVFT XF TFF UZQF


DMBTT JOGPSNBUJPO JOTUFBE PG B DPODSFUF UZQF CFDBVTF UIF DPN
QJMFS EPFTOƊU LOPX XIJDI TQFDJƶD OVNFSJD UZQF B WBMVF JT VOUJM
UIF UZQF JT FJUIFS EFDMBSFE PS UIF DPNQJMFS JT GPSDFE UP JOGFS
B TQFDJƶD UZQF CBTFE PO UIF GVODUJPO 'PS FYBNQMF  NBZ
MPPL MJLF BO JOUFHFS UP VT CVU UIBU XPVME POMZ BMMPX VT UP VTF JU
JO DPNQVUBUJPOT UIBU UBLF JOUFHFST BOE OPU TBZ JO GSBDUJPOBM
EJWJTJPO
 'PS UIBU SFBTPO UIF DPNQJMFS HJWFT JU UIF UZQF XJUI
UIF CSPBEFTU BQQMJDBCJMJUZ NPTU QPMZNPSQIJD
BOE TBZT JUƊT B
DPOTUSBJOFE QPMZNPSQIJD Num a => a WBMVF

Prelude> :type 13
13 :: Num a => a

-- we can give it a concrete type


-- by declaring it
Prelude> let x = 13 :: Integer
Prelude> :t x
x :: Integer
$)"15&3  5:1&4 

1PMZNPSQIJTN QPMZNPSQIJD OVNFSBMT BOE UZQF JOGFSFODF


XJMM BMM CF BEESFTTFE JO NPSF EFUBJM MBUFS
:PV DBO BMTP RVFSZ UIF UZQF TJHOBUVSFT PG GVODUJPOT BT XFƊWF
TFFO

Prelude> :type not


not :: Bool -> Bool

5IJT UBLFT POF JOQVU PG B Bool WBMVF BOE SFUVSOT POF Bool
WBMVF (JWFO UIBU UZQF UIFSF BSFOƊU UPP NBOZ UIJOHT JU FWFO
DPVME EP

6OEFSTUBOEJOH UIF GVODUJPO UZQF


5IF BSSPX (->) JT UIF UZQF DPOTUSVDUPS GPS GVODUJPOT JO )BTLFMM
*UƊT CBLFE JOUP UIF MBOHVBHF CVU TZOUBDUJDBMMZ JU XPSLT JO WFSZ
NVDI UIF TBNF XBZ BT BMM UIF PUIFS UZQFT ZPVƊWF TFFO TP GBS *UƊT
B UZQF DPOTUSVDUPS MJLF Bool FYDFQU UIF (->) UZQF DPOTUSVDUPS
UBLFT BSHVNFOUT BOE IBT OP EBUB DPOTUSVDUPST

Prelude> :info (->)


data (->) a b
-- some further information is elided

'PVS UP CF QSFDJTF #VU JG XF BTTVNF UIBU UIF TUBOEBSE 1SFMVEF GVODUJPOT BSF HFOFSBMMZ
VTFGVM GVODUJPOT JU IFMQT OBSSPX JU EPXO DPOTJEFSBCMZ -BUFS XF XJMM TIPX ZPV IPX UP
DBMDVMBUF UIF DBSEJOBMJUZ PG UZQFT TVDI UIBU ZPV XJMM LOPX IPX NBOZ XBZT UIFSF BSF UP
EFƶOF TPNFUIJOH PG B QBSUJDVMBS UZQF
$)"15&3  5:1&4 

*G ZPV DPNQBSF UIJT UP UIF UZQF DPOTUSVDUPS GPS UIF UXP


UVQMF ZPV TFF UIF TJNJMBSJUZ

Prelude> :info (,)


data (,) a b = (,) a b

8F TBX FBSMJFS UIBU UIF UVQMF DPOTUSVDUPS OFFET UP CF BQQMJFE


UP UXP WBMVFT JO PSEFS UP DPOTUSVDU B UVQMF " GVODUJPO NVTU
TJNJMBSMZ IBWF UXP BSHVNFOUT ƈ POF JOQVU BOE POF SFTVMU ƈ
JO PSEFS UP CF B GVODUJPO 6OMJLF UIF UVQMF DPOTUSVDUPS UIPVHI
UIF GVODUJPO UZQF IBT OP EBUB DPOTUSVDUPST 5IF WBMVF UIBU
TIPXT VQ BU UFSN MFWFM JT UIF GVODUJPO 'VODUJPOT BSF WBMVFT
"T XFƊWF TBJE UIF IBMMNBSL PG B GVODUJPO JT UIBU JU DBO CF
BQQMJFE BOE UIF TUSVDUVSF PG UIF UZQF EFNPOTUSBUFT UIJT 5IF
BSSPX JT BO JOƶY PQFSBUPS UIBU IBT UXP QBSBNFUFST BOE BTTPDJBUFT
UP UIF SJHIU BMUIPVHI GVODUJPO BQQMJDBUJPO JT MFǒ BTTPDJBUJWF

5IF QBSBNFUFSJ[BUJPO TVHHFTUT UIBU XF XJMM BQQMZ UIF GVODUJPO
UP TPNF BSHVNFOU UIBU XJMM CF CPVOE UP UIF ƶSTU QBSBNFUFS
XJUI UIF TFDPOE QBSBNFUFS ԑ SFQSFTFOUJOH UIF SFUVSO PS SFTVMU
UZQF 8F XJMM DPWFS UIFTF UIJOHT JO NPSF EFUBJM UISPVHIPVU
UIJT DIBQUFS
-FUƊT SFUVSO UP SFBEJOH UZQF TJHOBUVSFT 5IF GVODUJPO fst JT
B WBMVF PG UZQF (a, b) -> a XIFSF -> JT BO JOƶY UZQF DPOTUSVDUPS
UIBU UBLFT UXP BSHVNFOUT

fst :: (a, b) -> a


-- [1] [2] [3]
$)"15&3  5:1&4 

 5IF ƶSTU QBSBNFUFS PG fst IBT UIF UZQF (a, b) /PUF UIBU
UIF UVQMF UZQF JUTFMG (,) UBLFT UXP BSHVNFOUT Ԑ BOE ԑ IFSF

 5IF GVODUJPO UZQF (->) IBT UXP QBSBNFUFST IFSF 0OF JT


(a, b) BOE POF JT UIF SFTVMU Ԑ

 5IF SFTVMU PG UIF GVODUJPO XIJDI IBT UZQF Ԑ *UƊT UIF TBNF
Ԑ UIBU XBT JO UIF UVQMF (a, b)

)PX EP XF LOPX JUƊT UIF TBNF Ԑ "T XF MFBSO NPSF BCPVU


UZQF WBSJBCMFT JU XJMM CFDPNF NPSF DMFBS IPX XF LOPX 8F DBO
TBZ UIBU XF LOPX UIF JOQVU UZQF Ԑ BOE UIF PVUQVU UZQF Ԑ NVTU
CF UIF TBNF UZQF BOE XF DBO TFF UIBU OPUIJOH IBQQFOT CFUXFFO
UIF JOQVU BOE UIF PVUQVU UIBU JT UIFSF JT OP PQFSBUJPO UIBU
DPNFT CFUXFFO UIFN UIBU DPVME USBOTGPSN UIBU Ԑ JOUP TPNF
PUIFS WBMVF PG UIBU UZQF 8FƊMM HP JOUP NPSF EFUBJM BCPVU UIPTF
QPJOUT MBUFS JO UIF DIBQUFS
-FUƊT MPPL BU BOPUIFS GVODUJPO

Prelude> :type length


length :: [a] -> Int

5IF length GVODUJPO UBLFT POF BSHVNFOU UIBU JT B MJTU ƈ OPUF


UIF TRVBSF CSBDLFUT ƈ BOE SFUVSOT BO Int SFTVMU 5IF Int SFTVMU
JO UIJT DBTF XJMM CF UIF OVNCFS PG JUFNT JO UIF MJTU 5IF UZQF PG
UIF JOIBCJUBOUT PG UIF MJTU JT MFǒ VOTQFDJƶFE UIJT GVODUJPO EPFT
OPU DBSF JO GBDU DBOOPU DBSF XIBU UZQFT PG WBMVFT BSF JOTJEF
UIF MJTU
$)"15&3  5:1&4 

5ZQFDMBTTDPOTUSBJOFE UZQF WBSJBCMFT


/FYU MFUƊT MPPL BU UIF UZQFT PG TPNF BSJUINFUJD GVODUJPOT :PV
NBZ SFDBMM UIBU UIF BDU PG XSBQQJOH BO JOƶY PQFSBUPS JO QBSFO
UIFTFT BMMPXT VT UP VTF UIF GVODUJPO KVTU MJLF B OPSNBM QSFƶY
GVODUJPO JODMVEJOH CFJOH BCMF UP RVFSZ UIF UZQF

Prelude> :type (+)


(+) :: Num a => a -> a -> a
Prelude> :type (/)
(/) :: Fractional a => a -> a -> a

5P EFTDSJCF UIFTF DBTVBMMZ XF DPVME TBZ BEEJUJPO UBLFT POF


OVNFSJD BSHVNFOU BEET JU UP B TFDPOE OVNFSJD BSHVNFOU PG
UIF TBNF UZQF BOE SFUVSOT B OVNFSJD WBMVF PG UIF TBNF UZQF
BT B SFTVMU 4JNJMBSMZ UIF GSBDUJPOBM EJWJTJPO GVODUJPO UBLFT B
GSBDUJPOBM WBMVF EJWJEFT JU CZ B TFDPOE GSBDUJPOBM WBMVF BOE
SFUVSOT B UIJSE GSBDUJPOBM WBMVF BT B SFTVMU 5IJT JTOƊU QSFDJTF
CVU JU XJMM EP GPS OPX
5IF DPNQJMFS HJWFT UIF MFBTU TQFDJƶD BOE NPTU HFOFSBM UZQF
JU DBO *OTUFBE PG MJNJUJOH UIJT GVODUJPO UP B DPODSFUF UZQF XF
HFU B UZQFDMBTTDPOTUSBJOFE QPMZNPSQIJD UZQF WBSJBCMF 8FƊMM
TBWF B GVMMFS FYQMBOBUJPO PG UZQFDMBTTFT GPS UIF OFYU DIBQUFS
8IBU XF OFFE UP LOPX IFSF JT UIBU FBDI UZQFDMBTT PƵFST B TUBO
EBSE TFU PG GVODUJPOT UIBU DBO CF VTFE BDSPTT TFWFSBM DPODSFUF
UZQFT 8IFO B UZQFDMBTT JT DPOTUSBJOJOH B UZQF WBSJBCMF JO UIJT
XBZ UIF WBSJBCMF DPVME SFQSFTFOU BOZ PG UIF DPODSFUF UZQFT
$)"15&3  5:1&4 

UIBU IBWF JOTUBODFT PG UIBU UZQFDMBTT TP UIBU TQFDJƶD PQFSBUJPOT


PO XIJDI UIF GVODUJPO EFQFOET BSF EFƶOFE GPS UIBU UZQF 8F
TBZ JUƊT DPOTUSBJOFE CFDBVTF XF TUJMM EPOƊU LOPX UIF DPODSFUF
UZQF PG Ԑ CVU XF EP LOPX JU DBO POMZ CF POF PG UIF UZQFT UIBU
IBT UIF SFRVJSFE UZQFDMBTT JOTUBODF
5IJT HFOFSBMJ[BUJPO PG OVNCFSIPPE JT XIBU MFUT VT VTF UIF
TBNF OVNFSJDBM MJUFSBMT UP SFQSFTFOU OVNFSJD WBMVFT PG EJG
GFSFOU UZQFT 8F DBO TUBSU XJUI B Num a => a WBMVF BOE UIFO
DSFBUF TQFDJƶD WFSTJPOT PG JU XJUI B DPODSFUF UZQF VTJOH UIF ::
UP BTTJHO B UZQF UP UIF WBMVF

Prelude> let fifteen = 15


Prelude> :t fifteen
fifteen :: Num a => a
Prelude> let fifteenInt = fifteen :: Int
Prelude> let fifteenDouble = fifteen :: Double
Prelude> :t fifteenInt
fifteenInt :: Int
Prelude> :t fifteenDouble
fifteenDouble :: Double

8F XFOU GSPN Num a => a UP Int BOE Double 5IJT XPSLT CF
DBVTF Int BOE Double FBDI IBWF BO JOTUBODF PG UIF Num UZQFDMBTT

Prelude> :info Num


[...irrelevant bits elided...]
instance Num Int -- Defined in ‘GHC.Num’
$)"15&3  5:1&4 

instance Num Double -- Defined in ‘GHC.Float’

4JODF UIFZ CPUI IBWF JOTUBODFT PG Num UIF PQFSBUJPOT GSPN


Num TVDI BT BEEJUJPO BSF EFƶOFE GPS CPUI PG UIFN

Prelude> fifteenInt + fifteenInt


30
Prelude> fifteenDouble + fifteenDouble
30.0

8F DBO BMTP NBLF NPSF TQFDJƶD WFSTJPOT PG PVS Num a => a


WBMVF OBNFE fifteen CZ VTJOH JU JO B XBZ UIBU SFRVJSFT JU UP
CFDPNF TPNFUIJOH NPSF TQFDJƶD

Prelude> fifteenDouble + fifteen


30.0
Prelude> fifteenInt + fifteen
30

8IBU XF DBOOPU EP JT UIJT

Prelude> fifteenDouble + fifteenInt

Couldn't match expected type ‘Double’


with actual type ‘Int’
In the second argument of ‘(+)’,
namely ‘fifteenInt’
In the expression: fifteenDouble + fifteenInt
$)"15&3  5:1&4 

8F DBOƊU BEE UIPTF UXP WBMVFT CFDBVTF UIFJS UZQFT BSF OP


MPOHFS QPMZNPSQIJD BOE UIFJS DPODSFUF UZQFT BSF EJƵFSFOU TP
UIFZ IBWF EJƵFSFOU EFƶOJUJPOT PG IPX UP JNQMFNFOU BEEJUJPO
5IF UZQF FSSPS NFTTBHF DPOUSBTUT UIF BDUVBM UZQF XJUI UIF FY
QFDUFE UZQF 5IF BDUVBM UZQF JT XIBU XF QSPWJEFE UIF FYQFDUFE
UZQF JT XIBU UIF DPNQJMFS FYQFDUFE 4JODF XF IBE fifteenDouble
BT PVS ƶSTU BSHVNFOU JU FYQFDUFE UIF TFDPOE WBMVF UP BMTP IBWF
UIF UZQF Double CVU JU BDUVBMMZ IBT UIF UZQF Int
" UZQF TJHOBUVSF NJHIU IBWF NVMUJQMF UZQFDMBTT DPOTUSBJOUT
PO POF PS NPSF PG UIF WBSJBCMFT :PV XJMM TPNFUJNFT TFF PS
XSJUF
UZQF TJHOBUVSFT TVDI BT

(Num a, Num b) => a -> b -> b

-- or

(Ord a, Num a) => a -> a -> Ordering

)FSF UIF DPOTUSBJOUT MPPL MJLF B UVQMF CVU UIFZ EPOƊU BEE
BOPUIFS GVODUJPO BSHVNFOU UIBU ZPV NVTU QSPWJEF BOE UIFZ
EPOƊU BQQFBS BT B UVQMF BU UIF WBMVF PS UFSN MFWFM /PUIJOH UP
UIF MFǒ PG UIF UZQFDMBTT BSSPX => TIPXT VQ BU UFSN MFWFM 5IF
UVQMF PG DPOTUSBJOUT EPFT SFQSFTFOU B QSPEVDU PS DPOKVODUJPO
PG DPOTUSBJOUT
*O UIF ƶSTU FYBNQMF BCPWF UIFSF BSF UXP DPOTUSBJOUT POF
GPS FBDI WBSJBCMF #PUI Ԑ BOE ԑ NVTU IBWF JOTUBODFT PG UIF
$)"15&3  5:1&4 

Num UZQFDMBTT *O UIF TFDPOE FYBNQMF CPUI PG UIF DPOTUSBJOUT


BSF PO UIF POF WBSJBCMF Ԑ ƈ UIBU JT Ԑ NVTU CF B UZQF UIBU
JNQMFNFOUT CPUI Ord BOE Num

&YFSDJTFT 5ZQF .BUDIJOH


#FMPX ZPVƊMM ƶOE B MJTU PG TFWFSBM TUBOEBSE GVODUJPOT XFƊWF
UBMLFE BCPVU QSFWJPVTMZ 6OEFS UIBU JT B MJTU PG UIFJS UZQF TJH
OBUVSFT .BUDI UIF GVODUJPO UP JUT UZQF TJHOBUVSF 5SZ UP EP
JU XJUIPVU QFFLJOH BU UIF UZQF TJHOBUVSFT FJUIFS JO UIF UFYU PS
JO ()$J
BOE UIFO DIFDL ZPVS XPSL :PV NBZ ƶOE JU FBTJFS UP
TUBSU GSPN UIF UZQFT BOE XPSL PVU XIBU ZPV UIJOL B GVODUJPO
PG UIBU UZQF XPVME EP

 'VODUJPOT

B
not
C
length
D
concat
E
head
F
(<)

 5ZQF TJHOBUVSFT

B
_ :: [a] -> a

C
_ :: [[a]] -> [a]
$)"15&3  5:1&4 

D
_ :: Bool -> Bool

E
_ :: [a] -> Int

F
_ :: Ord a => a -> a -> Bool

 $VSSZJOH
"T JO UIF MBNCEB DBMDVMVT BSHVNFOUT QMVSBM
JT B TIPSUIBOE
GPS UIF USVUI JO )BTLFMM BMM GVODUJPOT JO )BTLFMM UBLF POF BSHV
NFOU BOE SFUVSO POF SFTVMU 0UIFS QSPHSBNNJOH MBOHVBHFT
JG ZPV IBWF BOZ FYQFSJFODF XJUI UIFN UZQJDBMMZ BMMPX ZPV UP
EFƶOF GVODUJPOT UIBU DBO UBLF NVMUJQMF BSHVNFOUT 5IFSF JT
OP TVQQPSU GPS UIJT CVJMU JOUP )BTLFMM *OTUFBE UIFSF BSF TZO
UBDUJD DPOWFOJFODFT UIBU DPOTUSVDU DVSSJFE GVODUJPOT CZ EFGBVMU
$VSSZJOH SFGFST UP UIF OFTUJOH PG NVMUJQMF GVODUJPOT FBDI BD
DFQUJOH POF BSHVNFOU BOE SFUVSOJOH POF SFTVMU UP BMMPX UIF
JMMVTJPO PG NVMUJQMFQBSBNFUFS GVODUJPOT
5IF BSSPXT XFƊWF TFFO JO UZQF TJHOBUVSFT EFOPUF UIF GVOD
UJPO UZQF 8F MPPLFE BU UIF EBUBUZQF EFƶOJUJPO FBSMJFS CVU
MFUƊT SFWJFX

data (->) a b

*O PSEFS UP IBWF B GVODUJPO ZPV NVTU IBWF POF JOQVU UIF Ԑ


UP BQQMZ UIF GVODUJPO UP BOE ZPVƊMM HFU POF SFTVMU UIF ԑ CBDL
&BDI BSSPX JO B UZQF TJHOBUVSF SFQSFTFOUT POF BSHVNFOU BOE
POF SFTVMU XJUI UIF ƶOBM UZQF CFJOH UIF ƶOBM SFTVMU *G ZPV
$)"15&3  5:1&4 

BSF DPOTUSVDUJOH B GVODUJPO UIBU SFRVJSFT NVMUJQMF QBSBNFUFST


UIFO UIF ԑ DBO CF BOPUIFS GVODUJPO UIF Ԑ DBO CF BOPUIFS GVOD
UJPO BT XFMM XIJDI XFƊMM MPPL BU NPSF MBUFS
 *O UIBU DBTF KVTU
MJLF JO MBNCEB BCTUSBDUJPOT UIBU IBWF NVMUJQMF IFBET UIFZ BSF
OFTUFE
-FUƊT CSFBL UIJT EPXO CZ MPPLJOH BU UIF UZQF TJHOBUVSF GPS
BEEJUJPO B GVODUJPO UIBU OFFET NVMUJQMF JOQVUT

(+) :: Num a => a -> a -> a


-- | 1 |

(+) :: Num a => a -> a -> a


-- | 2 |

(+) :: Num a => a -> a -> a


-- [3]

 )FSF JT UIF UZQFDMBTT DPOTUSBJOU TBZJOH UIBU Ԑ NVTU IBWF


BO JOTUBODF PG Num "EEJUJPO JT EFƶOFE JO UIF Num UZQFDMBTT

 5IF CPVOEBSJFT PG  EFNBSDBUF XIBU ZPV NJHIU DBMM UIF


UXP QBSBNFUFST UP UIF GVODUJPO (+) CVU BMM GVODUJPOT JO
)BTLFMM UBLF POF BSHVNFOU BOE SFUVSO POF SFTVMU 5IJT JT
CFDBVTF GVODUJPOT JO )BTLFMM BSF OFTUFE MJLF .BUSZPTILB
EPMMT JO PSEFS UP BDDFQU ƌNVMUJQMFƍ BSHVNFOUT 5IF XBZ
UIF (->) UZQF DPOTUSVDUPS GPS GVODUJPOT XPSLT NFBOT a ->
a -> a SFQSFTFOUT TVDDFTTJWF GVODUJPO BQQMJDBUJPOT FBDI
$)"15&3  5:1&4 

UBLJOH POF BSHVNFOU BOE SFUVSOJOH POF SFTVMU 5IF EJƵFS


FODF JT UIBU UIF GVODUJPO BU UIF PVUFSNPTU MBZFS JT BDUVBMMZ
SFUVSOJOH BOPUIFS GVODUJPO UIBU BDDFQUT UIF OFYU BSHVNFOU
5IJT JT DBMMFE DVSSZJOH

 5IJT JT UIF SFTVMU UZQF GPS UIJT GVODUJPO *U XJMM CF B OVNCFS


PG UIF TBNF UZQF BT UIF UXP JOQVUT

5IF XBZ UIF UZQF DPOTUSVDUPS GPS GVODUJPOT (->) JT EFƶOFE


NBLFT DVSSZJOH UIF EFGBVMU JO )BTLFMM 5IJT JT CFDBVTF JU JT BO
JOƶY PQFSBUPS BOE SJHIU BTTPDJBUJWF #FDBVTF JU BTTPDJBUFT UP
UIF SJHIU UZQFT BSF JNQMJDJUMZ QBSFOUIFTJ[FE MJLF TP

f :: a -> a -> a

-- associates to

f :: a -> (a -> a)

BOE

map :: (a -> b) -> [a] -> [b]

-- associates into

map :: (a -> b) -> ([a] -> [b])


$)"15&3  5:1&4 

-FUƊT TFF JG XF DBO VOQBDL UIF OPUJPO PG B SJHIUBTTPDJBUJOH


JOƶY PQFSBUPS HJWJOH VT DVSSJFE GVODUJPOT 5IF BTTPDJBUJPO
IFSF PS HSPVQJOH JOUP QBSFOUIFTFT JT OPU UP DPOUSPM QSFDF
EFODF PS PSEFS PG FWBMVBUJPO JU POMZ TFSWFT UP HSPVQ UIF QB
SBNFUFST JOUP BSHVNFOU BOE SFTVMU TJODF UIFSF DBO POMZ CF
POF BSHVNFOU BOE POF SFTVMU QFS BSSPX 4JODF BMM UIF BSSPXT
IBWF UIF TBNF QSFDFEFODF UIF BTTPDJBUJWJUZ EPFT OPU DIBOHF
UIF QSFDFEFODF PS PSEFS PG FWBMVBUJPO
3FNFNCFS XIFO XF IBWF B MBNCEB FYQSFTTJPO UIBU BQQFBST
UP IBWF UXP QBSBNFUFST UIFZ BSF BDUVBMMZ OFTUFE MBNCEBT
"QQMZJOH UIF FYQSFTTJPO UP POF BSHVNFOU SFUVSOT B GVODUJPO
UIBU BXBJUT BQQMJDBUJPO UP B TFDPOE BSHVNFOU "ǒFS ZPV BQQMZ
JU UP B TFDPOE BSHVNFOU ZPV IBWF B ƶOBM SFTVMU :PV DBO OFTU
NPSF MBNCEBT UIBO UXP PG DPVSTF CVU UIF QSPDFTT JT UIF TBNF
POF BSHVNFOU POF SFTVMU FWFO UIPVHI UIBU SFTVMU NBZ CF B
GVODUJPO BXBJUJOH BQQMJDBUJPO UP BOPUIFS BSHVNFOU
5IF UZQF DPOTUSVDUPS GPS GVODUJPOT BOE UIF UZQFT XF TFF
BCPWF BSF UIF TBNF UIJOH CVU XSJUUFO JO )BTLFMM 8IFO UIFSF
BSF ƌUXP BSHVNFOUTƍ JO )BTLFMM XF BQQMZ PVS GVODUJPO UP BO
BSHVNFOU KVTU MJLF XIFO XF BQQMZ B MBNCEB FYQSFTTJPO UP BO
BSHVNFOU BOE UIFO SFUVSO B SFTVMU UIBU JT B GVODUJPO BOE OFFET
UP CF BQQMJFE UP B TFDPOE BSHVNFOU
&YQMJDJU QBSFOUIFTJ[BUJPO BT XIFO BO JOQVU QBSBNFUFS JT
JUTFMG B GVODUJPO TVDI BT JO map BCPWF
NBZ CF VTFE UP JOEJDBUF
PSEFS PG FWBMVBUJPO CVU UIF JNQMJDJU BTTPDJBUJWJUZ PG UIF GVOD
UJPO UZQF EPFT OPU NFBO UIF JOOFS PS ƶOBM TFU PG QBSFOUIFTFT
$)"15&3  5:1&4 

JF UIF SFTVMU UZQF FWBMVBUFT ƶSTU "QQMJDBUJPO JT FWBMVBUJPO


JO PUIFS XPSET UIF POMZ XBZ UP FWBMVBUF BOZUIJOH JT CZ BQQMZ
JOH GVODUJPOT BOE GVODUJPO BQQMJDBUJPO JT MFǕ BTTPDJBUJWF 4P
UIF MFǒNPTU PS PVUFSNPTU BSHVNFOUT XJMM CF FWBMVBUFE ƶSTU
BTTVNJOH BOZUIJOH HFUT FWBMVBUFE TJODF )BTLFMM JT OPOTUSJDU
ZPV DBOƊU BTTVNF UIBU BOZUIJOH XJMM CF FWBMVBUFE CVU UIJT XJMM
CF NPSF DMFBS MBUFS


1BSUJBM BQQMJDBUJPO
$VSSZJOH NBZ CF JOUFSFTUJOH CVU NBOZ QFPQMF XPOEFS XIBU
UIF QSBDUJDBM FƵFDU PS WBMVF PG DVSSZJOH JT 8FƊMM MPPL OPX BU
B TUSBUFHZ DBMMFE QBSUJBM BQQMJDBUJPO UP TFF XIBU DVSSZJOH EPFT
GPS VT *UƊT TPNFUIJOH XFƊMM FYQMPSF NPSF BT XF HP UISPVHI UIF
CPPL CVU XFƊMM TUBSU XJUI B SFMBUJWFMZ VODPNQMJDBUFE FYBNQMF

-- we use the double colon to assign a type


-- making the type concrete will eliminate
-- the typeclass constraint
addStuff :: Integer -> Integer -> Integer
addStuff a b = a + b + 5

4P addStuff BQQFBST UP UBLF UXP Integer BSHVNFOUT BOE SF


UVSO BO Integer SFTVMU #VU BǒFS MPBEJOH UIBU JO ()$J XF TFF
UIBU JU JT UBLJOH POF BSHVNFOU BOE SFUVSOJOH B GVODUJPO UIBU
UBLFT POF BSHVNFOU BOE SFUVSOT POF SFTVMU
$)"15&3  5:1&4 

Prelude> :t addStuff
addStuff :: Integer -> Integer -> Integer
Prelude> let addTen = addStuff 5
Prelude> :t addTen
addTen :: Integer -> Integer
Prelude> let fifteen = addTen 5
Prelude> fifteen
15
Prelude> addTen 15
25
Prelude> addStuff 5 5
15

)FSF fifteen JT FRVBM UP addStuff 5 5 CFDBVTF addTen JT FRVBM


UP addStuff 5 5IF BCJMJUZ UP BQQMZ POMZ TPNF PG B GVODUJPOƊT BS
HVNFOUT JT DBMMFE QBSUJBM BQQMJDBUJPO 5IJT MFUT VT SFVTF addStuff
BOE DSFBUF B OFX GVODUJPO GSPN JU XJUI POF PG UIF BSHVNFOUT
BQQMJFE
*G XF SFDBMM UIBU (->) JT B UZQF DPOTUSVDUPS BOE BTTPDJBUFT UP
UIF SJHIU UIJT CFDPNFT NPSF DMFBS

addStuff :: Integer -> Integer -> Integer

-- but with explicit parenthesization

addStuff :: Integer -> (Integer -> Integer)


$)"15&3  5:1&4 

"QQMZJOH addStuff UP POF Integer BSHVNFOU HBWF VT UIF GVOD


UJPO addTen XIJDI JT UIF SFUVSO GVODUJPO PG addStuff "QQMZJOH
addTen UP BO Integer BSHVNFOU HJWFT VT B SFUVSO WBMVF TP UIF
UZQF PG fifteen JT Integer ƈ OP NPSF GVODUJPO BSSPXT
-FUƊT DIFDL PVS VOEFSTUBOEJOH XJUI B GVODUJPO UIBU JTOƊU
DPNNVUBUJWF

subtractStuff :: Integer -> Integer -> Integer


subtractStuff x y = x - y - 10
subtractOne = subtractStuff 1

Prelude> :t subtractOne
subtractOne :: Integer -> Integer
Prelude> let result = subtractOne 11
Prelude> result
-20

8IZ EJE XF HFU UIJT SFTVMU #FDBVTF PG UIF PSEFS JO XIJDI


XF BQQMJFE BSHVNFOUT result JT FRVBM UP 1 - 11 - 10

.BOVBM DVSSZJOH BOE VODVSSZJOH


)BTLFMM JT DVSSJFE CZ EFGBVMU CVU ZPV DBO VODVSSZ GVODUJPOT
6ODVSSZJOH NFBOT VOOFTUJOH UIF GVODUJPOT BOE SFQMBDJOH UIF
UXP GVODUJPOT XJUI B UVQMF PG UXP WBMVFT UIFTF XPVME CF UIF UXP
WBMVFT ZPV XBOU UP VTF BT BSHVNFOUT
 *G ZPV VODVSSZ (+) UIF
UZQF DIBOHFT GSPN Num a => a -> a -> a UP Num a => (a, a) -> a
$)"15&3  5:1&4 

XIJDI CFUUFS ƶUT UIF EFTDSJQUJPO ƌUBLFT UXP BSHVNFOUT SFUVSOT


POF SFTVMUƍ UIBO DVSSJFE GVODUJPOT 4PNF PMEFS GVODUJPOBM
MBOHVBHFT EFGBVMU UP VTJOH B QSPEVDU UZQF MJLF UVQMFT UP FYQSFTT
NVMUJQMF BSHVNFOUT

Ƒ 6ODVSSJFE GVODUJPOT 0OF GVODUJPO NBOZ BSHVNFOUT

Ƒ $VSSJFE GVODUJPOT .BOZ GVODUJPOT POF BSHVNFOU BQJFDF

:PV DBO BMTP EFTVHBS UIF BVUPNBUJD DVSSZJOH ZPVSTFMG CZ


OFTUJOH UIF BSHVNFOUT XJUI MBNCEBT UIPVHI UIFSFƊT BMNPTU
OFWFS B SFBTPO UP EP TP
8FƊMM VTF BOPOZNPVT MBNCEB TZOUBY IFSF UP TIPX ZPV TPNF
FYBNQMFT PG VODVSSZJOH :PV NBZ XBOU UP SFWJFX BOPOZNPVT
MBNCEB TZOUBY PS USZ DPNQBSJOH UIFTF GVODUJPOT EJSFDUMZ BOE
UIJOLJOH PG UIF CBDLTMBTI BT B MBNCEB

nonsense :: Bool -> Integer


nonsense True = 805
nonsense False = 31337

curriedFunction :: Integer
-> Bool
-> Integer
curriedFunction i b =
i + (nonsense b)
$)"15&3  5:1&4 

uncurriedFunction :: (Integer, Bool)


-> Integer
uncurriedFunction (i, b) =
i + (nonsense b)

anonymous :: Integer -> Bool -> Integer


anonymous = \i b -> i + (nonsense b)

anonNested :: Integer
-> Bool
-> Integer
anonNested =
\i -> \b -> i + (nonsense b)

5IFO XIFO XF UFTU UIF GVODUJPOT GSPN UIF 3&1-

Prelude> curriedFunction 10 False


31347
Prelude> anonymous 10 False
31347
Prelude> anonNested 10 False
31347

5IFZ BSF BMM UIF TBNF GVODUJPO BMM HJWJOH UIF TBNF SFTVMUT
*O anonNested XF NBOVBMMZ OFTUFE UIF BOPOZNPVT MBNCEBT UP
HFU B GVODUJPO UIBU XBT TFNBOUJDBMMZ JEFOUJDBM UP curriedFunction
$)"15&3  5:1&4 

CVU EJEOƊU MFWFSBHF UIF BVUPNBUJD DVSSZJOH 5IJT NFBOT GVOD


UJPOT UIBU TFFN UP BDDFQU NVMUJQMF BSHVNFOUT TVDI BT XJUI a ->
a -> a -> a BSF IJHIFSPSEFS GVODUJPOT UIFZ ZJFME NPSF GVODUJPO
WBMVFT BT FBDI BSHVNFOU JT BQQMJFE VOUJM UIFSF BSF OP NPSF (->)
UZQF DPOTUSVDUPST BOE JU UFSNJOBUFT JO B OPOGVODUJPO WBMVF

$VSSZJOH BOE VODVSSZJOH FYJTUJOH GVODUJPOT


*U UVSOT PVU XF DBO DVSSZ BOE VODVSSZ GVODUJPOT XJUI NVMUJQMF
QBSBNFUFST HFOFSJDBMMZ XJUIPVU XSJUJOH OFX DPEF GPS FBDI POF
$POTJEFS UIF GPMMPXJOH FYBNQMF GPS DVSSZJOH

Prelude> let curry f a b = f (a, b)


Prelude> :t curry
curry :: ((t1, t2) -> t) -> t1 -> t2 -> t
Prelude> :t fst
fst :: (a, b) -> a
Prelude> :t curry fst
curry fst :: t -> b -> t
Prelude> fst (1, 2)
1
Prelude> curry fst 1 2
1

5IFO GPS VODVSSZJOH

Prelude> let uncurry f (a, b) = f a b


$)"15&3  5:1&4 

Prelude> :t uncurry
uncurry :: (t1 -> t2 -> t) -> (t1, t2) -> t
Prelude> :t (+)
(+) :: Num a => a -> a -> a
Prelude> (+) 1 2
3
Prelude> uncurry (+) (1, 2)
3

$VSSZJOH BOE VODVSSZJOH GVODUJPOT PG UISFF PS NPSF BSHV


NFOUT BVUPNBUJDBMMZ JT RVJUF QPTTJCMF CVU USJDLJFS 8FƊMM MFBWF
UIBU CF CVU JOWFTUJHBUF PO ZPVS PXO JG ZPV MJLF

4FDUJPOJOH
8F NFOUJPOFE TFDUJPOJOH JO $IBQUFS  BOE OPX UIBU XFƊWF
UBMLFE B CJU NPSF BCPVU DVSSZJOH BOE QBSUJBM BQQMJDBUJPO JU
TIPVME CF NPSF DMFBS XIBUƊT IBQQFOJOH UIFSF 5IF UFSN TFDUJPO
JOH TQFDJƶDBMMZ SFGFST UP QBSUJBM BQQMJDBUJPO PG JOƶY PQFSBUPST
XIJDI IBT B TQFDJBM TZOUBY BOE BMMPXT ZPV UP DIPPTF XIFUIFS
UIF BSHVNFOU ZPVƊSF QBSUJBMMZ BQQMZJOH UIF PQFSBUPS UP JT UIF
ƶSTU PS TFDPOE BSHVNFOU

Prelude> let x = 5
Prelude> let y = (2^)
Prelude> let z = (^2)
Prelude> y x
$)"15&3  5:1&4 

32
Prelude> z x
25

8JUI DPNNVUBUJWF GVODUJPOT TVDI BT BEEJUJPO UIF BSHV


NFOU PSEFS EPFT OPU NBUUFS 8F XJMM VTVBMMZ TFDUJPO BEEJUJPO
BT GPS FYBNQMF (+3) CVU MBUFS XIFO XF TUBSU VTJOH QBSUJBMMZ
BQQMJFE GVODUJPOT B MPU XJUI NBQT BOE GPMET BOE TP GPSUI ZPVƊMM
CF BCMF UP TFF UIF EJƵFSFODF UIBU UIF BSHVNFOU PSEFS DBO NBLF
XJUI OPODPNNVUBUJWF PQFSBUPST
5IJT EPFT OPU POMZ XPSL XJUI BSJUINFUJD UIPVHI

Prelude> let celebrate = (++ " woot!")


Prelude> celebrate "naptime"
"naptime woot!"
Prelude> celebrate "dogs"
"dogs woot!"

:PV DBO BMTP VTF UIF TZOUBY XJUI GVODUJPOT UIBU BSF OPSNBMMZ
QSFƶY JG ZPV VTF UIF CBDLUJDLT UP NBLF UIFN JOƶY OPUF UIF
.. JT B TIPSUIBOE GPS DPOTUSVDUJOH B MJTU PG BMM UIF FMFNFOUT
CFUXFFO UIF ƶSTU BOE MBTU WBMVFT HJWFO ƈ HP BIFBE BOE QMBZ
XJUI UIJT JO ZPVS 3&1-


Prelude> elem 9 [1..10]


True
Prelude> 9 `elem` [1..10]
$)"15&3  5:1&4 

True
Prelude> let c = (`elem` [1..10])
Prelude> c 9
True
Prelude> c 25
False

*G ZPV QBSUJBMMZ BQQMJFE elem JO JUT VTVBM QSFƶY GPSN UIFO


UIF BSHVNFOU ZPV BQQMZ JU UP XPVME OFDFTTBSJMZ CF UIF ƶSTU
BSHVNFOU

Prelude> let hasTen = elem 10


Prelude> hasTen [1..9]
False
Prelude> hasTen [5..15]
True

1BSUJBM BQQMJDBUJPO JT DPNNPO FOPVHI JO )BTLFMM UIBU PWFS


UJNF ZPVƊMM EFWFMPQ BO JOUVJUJPO GPS JU 5IF TFDUJPOJOH TZOUBY
FYJTUT UP BMMPX TPNF GSFFEPN JO XIJDI BSHVNFOU PG B CJOBSZ
PQFSBUPS ZPV BQQMZ UIF GVODUJPO UP

&YFSDJTFT 5ZQF "SHVNFOUT


(JWFO B GVODUJPO BOE JUT UZQF UFMM VT XIBU UZQF SFTVMUT GSPN
BQQMZJOH TPNF PS BMM PG UIF BSHVNFOUT
:PV DBO DIFDL ZPVS XPSL JO UIF 3&1- MJLF UIJT VTJOH UIF
ƶSTU RVFTUJPO BT BO FYBNQMF

$)"15&3  5:1&4 

Prelude> let f :: a -> a -> a -> a; f = undefined


Prelude> let x :: Char; x = undefined
Prelude> :t f x

*U UVSOT PVU UIBU ZPV DBO DIFDL UIF UZQFT PG UIJOHT UIBU BSFOƊU
SFBMMZ JNQMFNFOUFE ZFU TP MPOH BT ZPV HJWF ()$J BO VOEFƶOFE
UP CJOE UIF TJHOBUVSF UP

 *G UIF UZQF PG f JT a -> a -> a -> a BOE UIF UZQF PG ԧ JT Char


UIFO UIF UZQF PG f x JT

B
Char -> Char -> Char
C
x -> x -> x -> x
D
a -> a -> a
E
a -> a -> a -> Char

 *G UIF UZQF PG g JT a -> b -> c -> b UIFO UIF UZQF PG


g 0 'c' "woot" JT

B
String
C
Char -> String
D
Int
E
Char

 *G UIF UZQF PG h JT (Num a, Num b) => a -> b -> b UIFO UIF


UZQF PG
h 1.0 2 JT
$)"15&3  5:1&4 

B
Double
C
Integer
D
Integral b => b
E
Num b => b

/PUF UIBU CFDBVTF UIF UZQF WBSJBCMFT Ԑ BOE ԑ BSF EJƵFSFOU


UIF DPNQJMFS NVTU BTTVNF UIBU UIF UZQFT DPVME CF EJƵFSFOU

 *G UIF UZQF PG h JT (Num a, Num b) => a -> b -> b UIFO UIF


UZQF PG
h 1 (5.5 :: Double) JT

B
Integer
C
Fractional b => b
D
Double
E
Num b => b

 *G UIF UZQF PG jackal JT (Ord a, Eq b) => a -> b -> a UIFO


UIF UZQF PG
jackal "keyboard" "has the word jackal in it"

B
[Char]
C
Eq b => b
D
b -> [Char]
E
b
$)"15&3  5:1&4 

F
Eq b => b -> [Char]

 *G UIF UZQF PG jackal JT (Ord a, Eq b) => a -> b -> a UIFO


UIF UZQF PG
jackal "keyboard"

B
b
C
Eq b => b
D
[Char]
E
b -> [Char]
F
Eq b => b -> [Char]

 *G UIF UZQF PG kessel JT (Ord a, Num b) => a -> b -> a UIFO


UIF UZQF PG
kessel 1 2 JT

B
Integer
C
Int
D
a
E
(Num a, Ord a) => a
F
Ord a => a
G
Num a => a

 *G UIF UZQF PG kessel JT (Ord a, Num b) => a -> b -> a UIFO


UIF UZQF PG
kessel 1 (2 :: Integer) JT
$)"15&3  5:1&4 

B
(Num a, Ord a) => a
C
Int
D
a
E
Num a => a
F
Ord a => a
G
Integer

 *G UIF UZQF PG kessel JT (Ord a, Num b) => a -> b -> a UIFO


UIF UZQF PG
kessel (1 :: Integer) 2 JT

B
Num a => a
C
Ord a => a
D
Integer
E
(Num a, Ord a) => a
F
a

 1PMZNPSQIJTN
1PMZNPSQI JT B XPSE PG SFMBUJWFMZ SFDFOU QSPWFOBODF *U XBT
JOWFOUFE JO UIF FBSMZ UI DFOUVSZ GSPN UIF (SFFL XPSET QPMZ
GPS ƌNBOZƍ BOE NPSQI GPS ƌGPSNƍ 5IF JD TVƸY JO QPMZNPSQIJD
NFBOT ƌNBEF PGƍ 4P ƉQPMZNPSQIJDƊ NFBOT ƌNBEF PG NBOZ
GPSNTƍ *O QSPHSBNNJOH UIJT JT VOEFSTUPPE UP CF JO DPOUSBTU
XJUI NPOPNPSQIJD ƌNBEF PG POF GPSNƍ
$)"15&3  5:1&4 

1PMZNPSQIJD UZQF WBSJBCMFT HJWF VT UIF BCJMJUZ UP JNQMFNFOU


FYQSFTTJPOT UIBU DBO BDDFQU BSHVNFOUT BOE SFUVSO SFTVMUT PG
EJƵFSFOU UZQFT XJUIPVU IBWJOH UP XSJUF WBSJBUJPOT PO UIF TBNF
FYQSFTTJPO GPS FBDI UZQF *U XPVME CF JOFƸDJFOU JG ZPV XFSF
EPJOH BSJUINFUJD BOE IBE UP XSJUF UIF TBNF DPEF PWFS BOE
PWFS GPS EJƵFSFOU OVNFSJD UZQFT 5IF HPPE OFXT JT UIF OV
NFSJDBM GVODUJPOT UIBU DPNF XJUI ZPVS ()$ JOTUBMMBUJPO BOE
UIF Prelude BSF QPMZNPSQIJD CZ EFGBVMU #SPBEMZ TQFBLJOH
UZQF TJHOBUVSFT NBZ IBWF UISFF LJOET PG UZQFT DPODSFUF DPO
TUSBJOFE QPMZNPSQIJD PS QBSBNFUSJDBMMZ QPMZNPSQIJD
*O )BTLFMM QPMZNPSQIJTN EJWJEFT JOUP UXP DBUFHPSJFT QBSB
NFUSJD QPMZNPSQIJTN BOE DPOTUSBJOFE QPMZNPSQIJTN *G ZPVƊWF
FODPVOUFSFE QPMZNPSQIJTN CFGPSF JU XBT QSPCBCMZ B GPSN
PG DPOTUSBJOFE PǒFO DBMMFE BEIPD QPMZNPSQIJTN "EIPD
QPMZNPSQIJTN JO )BTLFMM JT JNQMFNFOUFE XJUI UZQFDMBTTFT
1BSBNFUSJD QPMZNPSQIJTN JT CSPBEFS UIBO BEIPD QPMZNPS
QIJTN 1BSBNFUSJD QPMZNPSQIJTN SFGFST UP UZQF WBSJBCMFT PS
QBSBNFUFST UIBU BSF GVMMZ QPMZNPSQIJD 8IFO VODPOTUSBJOFE
CZ B UZQFDMBTT UIFJS ƶOBM DPODSFUF UZQF DPVME CF BOZUIJOH
$POTUSBJOFE QPMZNPSQIJTN PO UIF PUIFS IBOE QVUT UZQFDMBTT
DPOTUSBJOUT PO UIF WBSJBCMF EFDSFBTJOH UIF OVNCFS PG DPODSFUF
UZQFT JU DPVME CF CVU JODSFBTJOH XIBU ZPV DBO BDUVBMMZ EP XJUI
JU CZ EFƶOJOH BOE CSJOHJOH JOUP TDPQF B TFU PG PQFSBUJPOT
3FDBMM UIBU XIFO ZPV TFF B MPXFSDBTF OBNF JO B UZQF TJH

8BEMFSƊT QBQFS PO NBLJOH "EIPD QPMZNPSQIJTN MFTT BEIPD http://people.csail.
mit.edu/dnj/teaching/6898/papers/wadler88.pdf
$)"15&3  5:1&4 

OBUVSF JU JT B UZQF WBSJBCMF BOE QPMZNPSQIJD MJLF Ԑ ԣ FUD


 *G
UIF UZQF JT DBQJUBMJ[FE JU JT B TQFDJƶD DPODSFUF UZQF TVDI BT Int
Bool FUD
-FUƊT DPOTJEFS B QBSBNFUSJDBMMZ QPMZNPSQIJD GVODUJPO JEFO
UJUZ 5IF id GVODUJPO DPNFT XJUI UIF )BTLFMM 1SFMVEF BOE JT
DBMMFE UIF JEFOUJUZ GVODUJPO CFDBVTF JU JT UIF JEFOUJUZ GPS BOZ
WBMVF JO PVS MBOHVBHF *O UIF OFYU FYBNQMF UIF UZQF WBSJBCMF
ƉBƊ JT QBSBNFUSJDBMMZ QPMZNPSQIJD BOE OPU DPOTUSBJOFE CZ B
UZQFDMBTT 1BTTJOH BOZ WBMVF UP id XJMM SFUVSO UIF TBNF WBMVF

id :: a -> a
-- For all 'a', get an argument of some type 'a',
-- return value of same type 'a'

5IJT JT UIF NBYJNBMMZ QPMZNPSQIJD TJHOBUVSF GPS id *U


BMMPXT UIJT GVODUJPO UP XPSL XJUI BOZ UZQF PG EBUB

Prelude> id 1
1
Prelude> id "blah"
"blah"
Prelude> let inc = (+1)
Prelude> inc 2
3
Prelude> (id inc) 2
3
$)"15&3  5:1&4 

#BTFE PO UIF UZQF PG id XF BSF HVBSBOUFFE UIJT CFIBWJPS ƈ


JU DBOOPU EP BOZUIJOH FMTF 5IF Ԑ JO UIF UZQF TJHOBUVSF DBOOPU
DIBOHF CFDBVTF UIF UZQF WBSJBCMF HFUT ƶYFE UP B DPODSFUF UZQF
UISPVHIPVU UIF FOUJSF UZQF TJHOBUVSF B  B
 *G POF BQQMJFT
id UP B WBMVF PG UZQF Int UIF Ԑ JT ƶYFE UP UZQF Int #Z EFGBVMU
UZQF WBSJBCMFT BSF SFTPMWFE BU UIF MFǒNPTU QBSU PG UIF UZQF
TJHOBUVSF BOE BSF ƶYFE PODF TVƸDJFOU JOGPSNBUJPO UP CJOE
UIFN UP B DPODSFUF UZQF JT BWBJMBCMF
5IF BSHVNFOUT JO QBSBNFUSJDBMMZ QPMZNPSQIJD GVODUJPOT
MJLF id DPVME CF BOZUIJOH BOZ UZQF PS UZQFDMBTT TP UIF UFSNT
PG UIF GVODUJPO BSF NPSF SFTUSJDUFE CFDBVTF UIFSF BSF OP NFUI
PET PS JOGPSNBUJPO BUUBDIFE UP UIFN 8JUI UIF UZQF id :: a
-> a JU DBO EP OPUIJOH PUIFS UIBO SFUVSO Ԑ CFDBVTF UIFSF JT
OP JOGPSNBUJPO PS NFUIPE BUUBDIFE UP JUT QBSBNFUFS BU BMM ƈ
OPUIJOH DBO CF EPOF XJUI Ԑ 0O UIF PUIFS IBOE B GVODUJPO MJLF
negate XJUI B TJNJMBSBQQFBSJOH UZQF TJHOBUVSF PG Num a => a
-> a DPOTUSBJOT UIF Ԑ WBSJBCMF BT BO JOTUBODF PG UIF Num UZQFDMBTT
/PX Ԑ IBT GFXFS DPODSFUF UZQFT JU DPVME CF CVU UIFSF JT B TFU PG
NFUIPET ZPV DBO VTF B TFU PG UIJOHT UIBU DBO CF EPOF XJUI Ԑ
*G B WBSJBCMF SFQSFTFOUT B TFU PG QPTTJCMF WBMVFT UIFO B UZQF
WBSJBCMF SFQSFTFOUT B TFU PG QPTTJCMF UZQFT 8IFO UIFSF JT OP
UZQFDMBTT DPOTUSBJOU UIF TFU PG QPTTJCMF UZQFT B WBSJBCMF DPVME
SFQSFTFOU JT FƵFDUJWFMZ VOMJNJUFE 5ZQFDMBTT DPOTUSBJOUT MJNJU
UIF TFU PG QPUFOUJBM UZQFT BOE UIVT QPUFOUJBM WBMVFT
XIJMF
BMTP QBTTJOH BMPOH UIF DPNNPO GVODUJPOT UIBU DBO CF VTFE
XJUI UIPTF WBMVFT
$)"15&3  5:1&4 

$PODSFUF UZQFT IBWF FWFO NPSF ƷFYJCJMJUZ JO UFSNT PG DPN


QVUBUJPO 5IJT IBT UP EP XJUI UIF BEEJUJWF OBUVSF PG UZQFDMBTTFT
'PS FYBNQMF BO Int JT POMZ BO Int CVU JU DBO NBLF VTF PG UIF
NFUIPET PG UIF Num BOE Integral UZQFDMBTTFT CFDBVTF JU IBT JO
TUBODFT PG CPUI 8F DBO EFTDSJCF Num BT B TVQFSDMBTT PG TFWFSBM
PUIFS OVNFSJD UZQFDMBTTFT UIBU BMM JOIFSJU PQFSBUJPOT GSPN Num

*O TVN JG B WBSJBCMF DPVME CF BOZUIJOH UIFO UIFSFƊT MJUUMF


UIBU DBO CF EPOF UP JU CFDBVTF JU IBT OP NFUIPET *G JU DBO CF
TPNF UZQFT TBZ B UZQF UIBU JT BO JOTUBODF PG Num
UIFO JU IBT
TPNF NFUIPET *G JU JT B DPODSFUF UZQF ZPV MPTF UIF UZQF ƷFYJ
CJMJUZ CVU EVF UP UIF BEEJUJWF OBUVSF PG UZQFDMBTT JOIFSJUBODF
HBJO NPSF QPUFOUJBM NFUIPET *UƊT JNQPSUBOU UP OPUF UIBU UIJT
JOIFSJUBODF FYUFOET EPXOXBSE GSPN B TVQFSDMBTT TVDI BT Num
UP TVCDMBTTFT TVDI BT Integral BOE UIFO Int CVU OPU UIF PUIFS
XBZ BSPVOE 5IBU JT JG TPNFUIJOH JT BO JOTUBODF PG Num CVU OPU
BO JOTUBODF PG Integral JU DBOƊU JNQMFNFOU UIF NFUIPET PG UIF
Integral UZQFDMBTT " TVCDMBTT DBOOPU PWFSSJEF UIF NFUIPET PG
JUT TVQFSDMBTT
" GVODUJPO JT QPMZNPSQIJD XIFO JUT UZQF TJHOBUVSF IBT WBSJ
BCMFT UIBU DBO SFQSFTFOU NPSF UIBO POF UZQF 5IBU JT JUT QBSBN
FUFST BSF QPMZNPSQIJD 1BSBNFUSJD QPMZNPSQIJTN SFGFST UP
GVMMZ QPMZNPSQIJD VODPOTUSBJOFE CZ B UZQFDMBTT
QBSBNFUFST
1BSBNFUSJDJUZ JT UIF QSPQFSUZ XF HFU GSPN IBWJOH QBSBNFUSJD
QPMZNPSQIJTN 1BSBNFUSJDJUZ NFBOT UIBU UIF CFIBWJPS PG B
GVODUJPO XJUI SFTQFDU UP UIF UZQFT PG JUT QBSBNFUSJDBMMZ QPMZ
$)"15&3  5:1&4 

NPSQIJD
BSHVNFOUT JT VOJGPSN 5IF CFIBWJPS DBO OPU DIBOHF
KVTU CFDBVTF JU XBT BQQMJFE UP BO BSHVNFOU PG B EJƵFSFOU UZQF

&YFSDJTFT 1BSBNFUSJDJUZ
"MM ZPV DBO SFBMMZ EP XJUI B QBSBNFUSJDBMMZ QPMZNPSQIJD WBMVF
JT QBTT PS OPU QBTT JU UP TPNF PUIFS FYQSFTTJPO 1SPWF UIBU UP
ZPVSTFMG XJUI UIFTF TNBMM EFNPOTUSBUJPOT

 (JWFO UIF UZQF a -> a XIJDI JT UIF UZQF GPS id BUUFNQU


UP NBLF B GVODUJPO UIBU JT OPU CPUUPN BOE UFSNJOBUFT
TVDDFTTGVMMZ UIBU EPFT TPNFUIJOH PUIFS UIBO SFUVSOJOH
UIF TBNF WBMVF 5IJT JT JNQPTTJCMF CVU ZPV TIPVME USZ JU
BOZXBZ

 8F DBO HFU B NPSF DPNGPSUBCMF BQQSFDJBUJPO PG QBSB


NFUSJDJUZ CZ MPPLJOH BU a -> a -> a 5IJT IZQPUIFUJDBM
GVODUJPO a -> a -> a IBT UXPƇBOE POMZ UXPƇJNQMFNFOUB
UJPOT 8SJUF CPUI QPTTJCMF WFSTJPOT PG a -> a -> a "ǒFS
EPJOH TP USZ UP WJPMBUF UIF DPOTUSBJOUT PG QBSBNFUSJDBMMZ
QPMZNPSQIJD WBMVFT XF PVUMJOFE BCPWF

 *NQMFNFOU a -> b -> b )PX NBOZ JNQMFNFOUBUJPOT DBO


JU IBWF %PFT UIF CFIBWJPS DIBOHF XIFO UIF UZQFT PG Ԑ
BOE ԑ DIBOHF
$)"15&3  5:1&4 

1PMZNPSQIJD DPOTUBOUT
8FƊWF TFFO UIBU UIFSF BSF TFWFSBM UZQFT PG OVNCFST JO )BTLFMM
BOE UIBU UIFSF BSF SFTUSJDUJPOT PO VTJOH EJƵFSFOU UZQFT PG OVN
CFST JO EJƵFSFOU GVODUJPOT #VU JOUVJUJWFMZ XF TFF JU XPVME CF
PEE JG XF DPVME OPU EP BSJUINFUJD BMPOH UIF MJOFT PG -10 + 6.3
8FMM MFUƊT USZ JU

Prelude> (-10) + 6.3


-3.7

5IBU XPSLT KVTU ƶOF 8IZ -FUƊT MPPL BU UIF UZQFT BOE TFF JG
XF DBO ƶOE PVU

Prelude> :t (-10) + 6.3


(-10) + 6.3 :: Fractional a => a
Prelude> :t (-10)
(-10) :: Num a => a

/VNFSJD MJUFSBMT MJLF 


BOE  BSF QPMZNPSQIJD BOE TUBZ
TP VOUJM HJWFO B NPSF TQFDJƶD UZQF 5IF Num a => PS Fractional
a => JT B UZQFDMBTT DPOTUSBJOU BOE UIF Ԑ JT UIF UZQF WBSJBCMF
JO TDPQF *O UIF UZQF GPS UIF FOUJSF FRVBUJPO XF TFF UIBU UIF
DPNQJMFS JOGFSSFE UIBU JU XBT XPSLJOH XJUI Fractional OVNCFST
*U IBE UP UP BDDPNNPEBUF UIF GSBDUJPOBM OVNCFS  'JOF
CVU XIBU BCPVU 
8F TFF UIBU UIF UZQF PG 
JT HJWFO
NBYJNVN QPMZNPSQIJTN CZ POMZ CFJOH BO JOTUBODF PG UIF
$)"15&3  5:1&4 

Num UZQFDMBTT XIJDI DPVME CF BOZ UZQF PG OVNCFS 8F DBMM


UIJT B QPMZNPSQIJD DPOTUBOU 
JT OPU B WBSJBCMF PG DPVSTF
CVU UIF UZQF UIBU JU JOTUBOUJBUFT DPVME CF BOZ OVNFSJD UZQF TP
JUT VOEFSMZJOH SFQSFTFOUBUJPO JT QPMZNPSQIJD *U XJMM IBWF UP
SFTPMWF JOUP B DPODSFUF UZQF BU TPNF QPJOU JO PSEFS UP FWBMVBUF

8F DBO GPSDF UIF DPNQJMFS UP CF NPSF TQFDJƶD BCPVU UIF


UZQFT PG OVNCFST CZ EFDMBSJOH UIF UZQF

Prelude> let x = 5 + 5
Prelude> :t x
x :: Num a => a
Prelude> let x = 5 + 5 :: Int
Prelude> :t x
x :: Int

*O UIF ƶSTU FYBNQMF XF EJE OPU TQFDJGZ B UZQF GPS UIF OVN
CFST TP UIF UZQF TJHOBUVSF EFGBVMUFE UP UIF CSPBEFTU JOUFSQSF
UBUJPO CVU JO UIF TFDPOE WFSTJPO XF UPME UIF DPNQJMFS UP VTF
UIF Int UZQF

8PSLJOH BSPVOE DPOTUSBJOUT


1SFWJPVTMZ XFƊWF MPPLFE BU B GVODUJPO DBMMFE length UIBU UBLFT
B MJTU BOE DPVOUT UIF OVNCFS PG NFNCFST BOE SFUVSOT UIBU
OVNCFS BT BO Int WBMVF 8F TBX JO UIF MBTU DIBQUFS UIBU CFDBVTF
Int JT OPU B Fractional OVNCFS UIJT GVODUJPO XPOƊU XPSL
$)"15&3  5:1&4 

Prelude> 6 / length [1, 2, 3]

No instance for (Fractional Int) arising


from a use of ‘/’

In the expression: 6 / length [1, 2, 3]


In an equation for ‘it’: it = 6 / length [1, 2, 3]

)FSF UIF QSPCMFN JT length JTOƊU QPMZNPSQIJD FOPVHI Fractional


JODMVEFT TFWFSBM UZQFT PG OVNCFST CVU Int JTOƊU POF PG UIFN
BOE UIBUƊT BMM length DBO SFUVSO )BTLFMM EPFT PƵFS XBZT UP
XPSL BSPVOE UIJT UZQF PG DPOƷJDU UIPVHI *O UIJT DBTF XF XJMM
VTF B GVODUJPO DBMMFE fromIntegral UIBU UBLFT BO JOUFHSBM WBMVF
BOE GPSDFT JU UP JNQMFNFOU UIF /VN UZQFDMBTT SFOEFSJOH JU
QPMZNPSQIJD )FSFƊT XIBU UIF UZQF TJHOBUVSF MPPLT MJLF

Prelude> :type fromIntegral


fromIntegral :: (Num b, Integral a) => a -> b

4P JU UBLFT B WBMVF Ԑ PG BO Integral UZQF BOE SFUVSOT JU BT


B WBMVF ԑ PG BOZ Num UZQF -FUƊT TFF IPX UIBU XPSLT XJUI PVS
GSBDUJPOBM EJWJTJPO QSPCMFN

Prelude> 6 / fromIntegral (length [1, 2, 3])


2.0

"OE OPX BMM JT SJHIU XJUI UIF XPSME PODF BHBJO


$)"15&3  5:1&4 

 5ZQF JOGFSFODF


)BTLFMM EPFT OPU PCMJHBUF VT UP BTTFSU B UZQF GPS FWFSZ FYQSFT
TJPO PS WBMVF JO PVS QSPHSBNT CFDBVTF JU IBT UZQF JOGFSFODF
5ZQF JOGFSFODF JT BO BMHPSJUIN GPS EFUFSNJOJOH UIF UZQFT PG
FYQSFTTJPOT )BTLFMMƊT UZQF JOGFSFODF JT CVJMU PO BO FYUFOEFE
WFSTJPO PG UIF %BNBT)JOEMFZ.JMOFS UZQF TZTUFN
)BTLFMM XJMM JOGFS UIF NPTU HFOFSBMMZ BQQMJDBCMF QPMZNPS
QIJD
UZQF UIBU JT TUJMM DPSSFDU &TTFOUJBMMZ UIF DPNQJMFS TUBSUT
GSPN UIF WBMVFT XIPTF UZQFT JU LOPXT BOE UIFO XPSLT PVU UIF
UZQFT PG UIF PUIFS WBMVFT "T ZPV NBUVSF BT B )BTLFMM QSP
HSBNNFS ZPVƊMM ƶOE UIJT JT QSJODJQBMMZ VTFGVM GPS XIFO ZPVƊSF
TUJMM ƶHVSJOH PVU OFX DPEF SBUIFS UIBO GPS DPEF UIBU JT ƌEPOFƍ
0ODF ZPVS QSPHSBN JT ƌEPOF ƍ ZPV XJMM DFSUBJOMZ LOPX UIF
UZQFT PG BMM UIF GVODUJPOT BOE JUƊT DPOTJEFSFE HPPE QSBDUJDF
UP FYQMJDJUMZ EFDMBSF UIFN 3FNFNCFS XIFO XF TVHHFTUFE
UIBU B HPPE UZQF TZTUFN XBT MJLF B QMFBTBOU DPOWFSTBUJPO XJUI
B DPMMFBHVF 5IJOL PG UZQF JOGFSFODF BT B IFMQGVM DPMMFBHVF
XPSLJOH UISPVHI B QSPCMFN XJUI ZPV
'PS FYBNQMF XF DBO XSJUF id PVSTFMWFT

Prelude> let ourId x = x


Prelude> :t ourId
ourId :: t -> t
Prelude> ourId 1
1
$)"15&3  5:1&4 

Prelude> ourId "blah"


"blah"

)FSF XF MFU ()$J JOGFS UIF UZQF PG ourId JUTFMG %VF UP BMQIB
FRVJWBMFODF UIF EJƵFSFODF JO MFUUFST ԣ IFSF WFSTVT Ԑ BCPWF

NBLFT OP EJƵFSFODF 5ZQF WBSJBCMFT IBWF OP NFBOJOH PVUTJEF


PG UIF UZQF TJHOBUVSFT XIFSF UIFZ BSF CPVOE
'PS UIJT GVODUJPO XF BHBJO BTL UIF DPNQJMFS UP JOGFS UIF
UZQF

Prelude> let myGreet x = x ++ " Julie"


Prelude> myGreet "hello"
"hello Julie"
Prelude> :type myGreet
myGreet :: [Char] -> [Char]

5IF DPNQJMFS LOPXT UIF GVODUJPO (++) BOE IBT POF WBMVF UP
XPSL XJUI BMSFBEZ UIBU JU LOPXT JT B String *U EPFTOƊU IBWF UP
XPSL WFSZ IBSE UP JOGFS B UZQF TJHOBUVSF GSPN UIBU JOGPSNBUJPO
*G IPXFWFS XF UBLF PVU UIF TUSJOH WBMVF BOE SFQMBDF JU XJUI
BOPUIFS WBSJBCMF TFF XIBU IBQQFOT

Prelude> let myGreet x y = x ++ y


Prelude> :type myGreet
myGreet :: [a] -> [a] -> [a]

8FƊSF CBDL UP B QPMZNPSQIJD UZQF TJHOBUVSF UIF TBNF TJH


OBUVSF GPS (++) JUTFMG CFDBVTF UIF DPNQJMFS IBT OP JOGPSNBUJPO
$)"15&3  5:1&4 

CZ XIJDI UP JOGFS UIF UZQFT GPS BOZ PG UIPTF WBSJBCMFT PUIFS


UIBO UIBU UIFZ BSF MJTUT PG TPNF TPSU

-FUƊT TFF UZQF JOGFSFODF BU XPSL 0QFO ZPVS FEJUPS PG DIPJDF
BOE FOUFS UIF GPMMPXJOH TOJQQFU

-- typeInference1.hs
module TypeInference1 where

f :: Num a => a -> a -> a


f x y = x + y + 3

5IFO MPBE UIF DPEF JOUP ()$J UP FYQFSJNFOU

Prelude> :l typeInference1.hs
[1 of 1] Compiling TypeInference1
Ok, modules loaded: TypeInference1.
Prelude> f 1 2
6
Prelude> :t f
f :: Num a => a -> a -> a
Prelude> :t f 1
f 1 :: Num a => a -> a

#FDBVTF UIF OVNFSJD MJUFSBMT JO )BTLFMM IBWF UIF UZQFDMBTT


DPOTUSBJOFE
QPMZNPSQIJD UZQF Num a => a XF EPOƊU HFU B NPSF
TQFDJƶD UZQF XIFO BQQMZJOH ԕ UP 
$)"15&3  5:1&4 

-PPL BU XIBU IBQQFOT XIFO XF FMJEF UIF FYQMJDJU UZQF TJH


OBUVSF GPS ԕ

-- typeInference2.hs
module TypeInference2 where

f x y = x + y + 3

/P UZQF TJHOBUVSF GPS ԕ TP EPFT JU DPNQJMF %PFT JU XPSL

Prelude> :l typeInference2.hs
[1 of 1] Compiling TypeInference2
Ok, modules loaded: TypeInference2.
Prelude> :t f
f :: Num a => a -> a -> a
Prelude> f 1 2
6

/PUIJOH DIBOHFT *O DFSUBJO DBTFT UIFSF NJHIU CF B DIBOHF


VTVBMMZ XIFO ZPV BSF VTJOH UZQFDMBTTFT JO B XBZ UIBU EPFTOƊU
NBLF JU DMFBS XIJDI UZQF ZPV NFBO VOMFTT ZPV BTTFSU POF

&YFSDJTFT "QQMZ :PVSTFMG


-PPL BU UIFTF QBJST PG GVODUJPOT 0OF GVODUJPO JT VOBQQMJFE
TP UIF DPNQJMFS XJMM JOGFS NBYJNBMMZ QPMZNPSQIJD UZQF 5IF
TFDPOE GVODUJPO IBT CFFO BQQMJFE UP B WBMVF TP UIF JOGFSSFE
$)"15&3  5:1&4 

UZQF TJHOBUVSF NBZ IBWF CFDPNF DPODSFUF PS BU MFBTU MFTT


QPMZNPSQIJD 'JHVSF PVU IPX UIF UZQF XPVME DIBOHF BOE XIZ
NBLF B OPUF PG XIBU ZPV UIJOL UIF OFX JOGFSSFE UZQF XPVME
CF BOE UIFO DIFDL ZPVS XPSL JO ()$J

 -- Type signature of general function


(++) :: [a] -> [a] -> [a]

-- How might that change when we apply


-- it to the following value?
myConcat x = x ++ " yo"

 -- General function
(*) :: Num a => a -> a -> a

-- Applied to a value
myMult x = (x / 3) * 5

 take :: Int -> [a] -> [a]

myTake x = take x "hey you"

 (>) :: Ord a => a -> a -> Bool

myCom x = x > (length [1..10])


$)"15&3  5:1&4 

 (<) :: Ord a => a -> a -> Bool

myAlph x = x < 'z'

 "TTFSUJOH UZQFT GPS EFDMBSBUJPOT


.PTU PG UIF UJNF XF XBOU UP EFDMBSF PVS UZQFT SBUIFS UIBO
SFMZJOH PO UZQF JOGFSFODF "EEJOH UZQF TJHOBUVSFT UP ZPVS DPEF
DBO QSPWJEF HVJEBODF UP ZPV BT ZPV XSJUF ZPVS GVODUJPOT *U
DBO BMTP IFMQ UIF DPNQJMFS HJWF ZPV JOGPSNBUJPO BCPVU XIFSF
ZPVS DPEF JT HPJOH XSPOH "T QSPHSBNT CFDPNF MPOHFS BOE
NPSF DPNQMFY UZQF TJHOBUVSFT CFDPNF FWFO NPSF JNQPSUBOU
BT UIFZ IFMQ ZPV PS PUIFS QSPHSBNNFST USZJOH UP VTF ZPVS
DPEF SFBE JU BOE ƶHVSF PVU XIBU JUƊT TVQQPTFE UP EP 5IJT
TFDUJPO XJMM MPPL BU IPX UP EFDMBSF UZQFT 8F XJMM TUBSU XJUI
TPNF USJWJBM FYBNQMFT
:PV NBZ SFNFNCFS UIF triple GVODUJPO XFƊWF TFFO CFGPSF
*G XF BMMPX UIF DPNQJMFS UP JOGFS UIF UZQF XF FOE VQ XJUI UIJT

Prelude> let triple x = x * 3


Prelude> :type triple
triple :: Num a => a -> a

)FSF UIF USJQMF GVODUJPO XBT NBEF GSPN UIF (*) GVODUJPO
XIJDI IBT UZQF (*) :: Num a => a -> a -> a CVU XF IBWF BM
SFBEZ BQQMJFE POF PG UIF BSHVNFOUT XIJDI JT UIF  TP UIFSF JT
$)"15&3  5:1&4 

POF MFTT QBSBNFUFS JO UIJT UZQF TJHOBUVSF *U JT TUJMM QPMZNPS


QIJD CFDBVTF JU DBOƊU UFMM XIBU UZQF  JT ZFU *G IPXFWFS XF
XBOU UP FOTVSF UIBU PVS JOQVUT BOE SFTVMU NBZ POMZ CF JOUFHFST
UIJT JT IPX XF EFDMBSF UIBU

Prelude> let triple x = x * 3 :: Integer


Prelude> :t triple
triple :: Integer -> Integer

-- Note the typeclass constraint is gone


-- because Integer implements Num
-- so that constraint is redundant.

)FSFƊT BOPUIFS FYBNQMF PG B UZQF EFDMBSBUJPO GPS PVS triple


GVODUJPO UIJT POF NPSF MJLF XIBU ZPV XPVME TFF JO B TPVSDF
ƶMF

-- declaration of triple's type


triple :: Integer -> Integer

-- declaration of the function


triple x = x * 3

5IJT JT IPX NPTU )BTLFMM DPEF ZPV MPPL BU XJMM CF MBJE PVU
XJUI TFQBSBUF UPQMFWFM EFDMBSBUJPOT GPS UZQFT BOE GVODUJPOT
4VDI UPQMFWFM EFDMBSBUJPOT BSF JO TDPQF UISPVHIPVU UIF NPE
VMF
$)"15&3  5:1&4 

*U JT QPTTJCMF UIPVHI VODPNNPO UP EFDMBSF UZQFT MPDBMMZ


XJUI let BOE where DMBVTFT )FSFƊT BO FYBNQMF PG BTTJHOJOH B
UZQF XJUIJO B where DMBVTF

triple x = tripleItYo x
where tripleItYo :: Integer -> Integer
tripleItYo y = y * 3

8F EPOƊU IBWF UP BTTFSU UIF UZQF PG triple

Prelude> :t triple
triple :: Integer -> Integer

5IF BTTFSUJPO JO UIF where DMBVTF OBSSPXFE PVS UZQF EPXO


GSPN Num a => a -> a UP Integer -> Integer ()$ XJMM QJDL VQ
BOE QSPQBHBUF UZQF JOGPSNBUJPO GPS JOGFSFODF GSPN BQQMJ
DBUJPOT PG GVODUJPOT TVCFYQSFTTJPOT EFƶOJUJPOT ƈ BMNPTU
BOZXIFSF 5IF UZQF JOGFSFODF JT TUSPOH XJUI UIJT POF
5IFSF BSF DPOTUSBJOUT PO PVS BCJMJUZ UP EFDMBSF UZQFT 'PS
FYBNQMF JG XF USZ UP NBLF UIF (+) GVODUJPO SFUVSO B String XF
HFU BO FSSPS NFTTBHF

Prelude> let x = 5 + 5 :: String

No instance for (Num String) arising from a use of ‘+’


In the expression: 5 + 5 :: String
In an equation for ‘x’: x = 5 + 5 :: String
$)"15&3  5:1&4 

5IJT GVODUJPO DBOOPU BDDFQU BSHVNFOUT PG UZQF String *O


UIJT DBTF JUƊT PWFSEFUFSNJOFE CPUI CFDBVTF UIF (+) GVODUJPO
JT MJNJUFE UP UZQFT JNQMFNFOUJOH UIF Num UZQFDMBTT BOE BMTP
CFDBVTF XFƊWF BMSFBEZ QBTTFE JU UXP OVNFSJD MJUFSBMT BT WBMVFT
5IF OVNFSJD MJUFSBMT DPVME CF BOZ PG TFWFSBM OVNFSJD UZQFT
VOEFS UIF IPPE CVU UIFZ DBOƊU CF String CFDBVTF String EPFT
OPU JNQMFNFOU UIF Num UZQFDMBTT

 $IBQUFS &YFSDJTFT


8FMDPNF UP BOPUIFS SPVOE PG ƌ,OPXJOH JT OPU FOPVHI XF
NVTU BQQMZƍ

.VMUJQMF DIPJDF
 " WBMVF PG UZQF [a] JT

B
B MJTU PG BMQIBCFUJD DIBSBDUFST
C
B MJTU PG MJTUT
D
B MJTU XIPTF FMFNFOUT BSF BMM PG TPNF UZQF Ԑ
E
B MJTU XIPTF FMFNFOUT BSF BMM PG EJƵFSFOU UZQFT

 " GVODUJPO PG UZQF [[a]] -> [a] DPVME

B
UBLF B MJTU PG TUSJOHT BT BO BSHVNFOU
C
USBOTGPSN B DIBSBDUFS JOUP B TUSJOH
$)"15&3  5:1&4 

D
USBOTGPSN B TUSJOH JO UP B MJTU PG TUSJOHT
E
UBLF UXP BSHVNFOUT

 " GVODUJPO PG UZQF [a] -> Int -> a

B
UBLFT POF BSHVNFOU
C
SFUVSOT POF FMFNFOU PG UZQF Ԑ GSPN B MJTU
D
NVTU SFUVSO BO Int WBMVF
E
JT DPNQMFUFMZ ƶDUJPOBM

 " GVODUJPO PG UZQF (a, b) -> a

B
UBLFT B MJTU BSHVNFOU BOE SFUVSOT B Char WBMVF
C
IBT [FSP BSHVNFOUT
D
UBLFT B UVQMF BSHVNFOU BOE SFUVSOT UIF ƶSTU WBMVF
E
SFRVJSFT UIBU Ԑ BOE ԑ CF PG EJƵFSFOU UZQFT

%FUFSNJOF UIF UZQF


'PS UIF GPMMPXJOH GVODUJPOT EFUFSNJOF UIF UZQF PG UIF TQFDJ
ƶFE WBMVF 8F TVHHFTU ZPV UZQF UIFN JOUP B ƶMF BOE MPBE UIF
DPOUFOUT PG UIF ƶMF JO ()$J *O BMM MJLFMJIPPE JU JOJUJBMMZ XJMM
OPU IBWF UIF QPMZNPSQIJD UZQFT ZPV NJHIU FYQFDU EVF UP UIF
NPOPNPSQIJTN SFTUSJDUJPO 8FƊMM FYQMBJO NPSF NVDI MBUFS CVU
GPS OPX JU NFBOT UIBU UPQMFWFM EFDMBSBUJPOT CZ EFGBVMU XJMM
IBWF B DPODSFUF UZQF JG BOZ DBO CF EFUFSNJOFE :PV DBO ƶY
UIJT CZ TFUUJOH VQ ZPVS ƶMF MJLF TP
$)"15&3  5:1&4 

{-# LANGUAGE NoMonomorphismRestriction #-}

module DetermineTheType where

-- simple example
example = 1

*G ZPV IBE OPU JODMVEFE UIF NoMonomorphismRestriction QSBHNB


example XPVME IBWF IBE UIF UZQF Integer JOTUFBE PG Num a => a
%P ZPVS CFTU UP EFUFSNJOF UIF NPTU QPMZNPSQIJD UZQF BO FY
QSFTTJPO DPVME IBWF JO UIF GPMMPXJOH FYFSDJTFT

 "MM GVODUJPO BQQMJDBUJPOT SFUVSO B WBMVF %FUFSNJOF UIF


WBMVF SFUVSOFE CZ UIFTF GVODUJPO BQQMJDBUJPOT BOE UIF UZQF
PG UIBU WBMVF

B
(* 9) 6

C
head [(0,"doge"),(1,"kitteh")]

D
head [(0 :: Integer ,"doge"),(1,"kitteh")]

E
if False then True else False

F
length [1, 2, 3, 4, 5]

G
(length [1, 2, 3, 4]) > (length "TACOCAT")

 (JWFO
$)"15&3  5:1&4 

x = 5
y = x + 5
w = y * 10

8IBU JT UIF UZQF PG X

 (JWFO

x = 5
y = x + 5
z y = y * 10

8IBU JT UIF UZQF PG [

 (JWFO

x = 5
y = x + 5
f = 4 / y

8IBU JT UIF UZQF PG G

 (JWFO

x = "Julie"
y = " <3 "
z = "Haskell"
f = x ++ y ++ z

8IBU JT UIF UZQF PG G


$)"15&3  5:1&4 

%PFT JU DPNQJMF
'PS FBDI TFU PG FYQSFTTJPOT ƶHVSF PVU XIJDI FYQSFTTJPO JG BOZ
DBVTFT UIF DPNQJMFS UP TRVBXL BU ZPV OC XF EP OPU NFBO
MJUFSBM TRVBXLJOH
BOE XIZ 'JY JU JG ZPV DBO

 bigNum = (^) 5 $ 10
wahoo = bigNum $ 10

 x = print
y = print "woohoo!"
z = x "hello world"

 a = (+)
b = 5
c = b 10
d = c 200

 a = 12 + b
b = 10000 * c

5ZQF WBSJBCMF PS TQFDJƶD UZQF DPOTUSVDUPS


 :PV XJMM CF TIPXO B UZQF EFDMBSBUJPO BOE ZPV TIPVME
DBUFHPSJ[F FBDI UZQF 5IF DIPJDFT BSF B GVMMZ QPMZNPSQIJD
UZQF WBSJBCMF DPOTUSBJOFE QPMZNPSQIJD UZQF WBSJBCMF PS
DPODSFUF UZQF DPOTUSVDUPS
$)"15&3  5:1&4 

f :: Num a => a -> b -> Int -> Int


-- [0] [1] [2] [3]

)FSF UIF BOTXFS XPVME CF DPOTUSBJOFE QPMZNPSQIJD


Num
<>
GVMMZ QPMZNPSQIJD <>
BOE DPODSFUF <> BOE
<>


 $BUFHPSJ[F FBDI DPNQPOFOU PG UIF UZQF TJHOBUVSF BT EF


TDSJCFE JO UIF QSFWJPVT FYBNQMF

f :: zed -> Zed -> Blah

 $BUFHPSJ[F FBDI DPNQPOFOU PG UIF UZQF TJHOBUVSF

f :: Enum b => a -> b -> C

 $BUFHPSJ[F FBDI DPNQPOFOU PG UIF UZQF TJHOBUVSF

f :: f -> g -> C

8SJUF B UZQF TJHOBUVSF


'PS UIF GPMMPXJOH FYQSFTTJPOT QMFBTF BEE B UZQF TJHOBUVSF :PV
TIPVME CF BCMF UP SFMZ PO ()$J UZQF JOGFSFODF UP DIFDL ZPVS
XPSL BMUIPVHI ZPV NJHIU OPU IBWF QSFDJTFMZ UIF TBNF BOTXFS
BT ()$J HJWFT EVF UP QPMZNPSQIJTN FUD


 8IJMF XF IBWFOƊU GVMMZ FYQMBJOFE UIJT TZOUBY ZFU ZPVƊWF


TFFO JU JO $IBQUFS  BOE BT B TPMVUJPO UP BO FYFSDJTF JO
$)"15&3  5:1&4 

$IBQUFS  5IJT TZOUBY JT B XBZ PG EFTUSVDUVSJOH B TJOHMF


FMFNFOU PG B MJTU

functionH ::
functionH (x:_) = x

 functionC ::
functionC x y = if (x > y) then True else False

 functionS ::
functionS (x, y) = y

(JWFO B UZQF XSJUF UIF GVODUJPO


:PV XJMM CF TIPXO B UZQF BOE B GVODUJPO UIBU OFFET UP CF XSJU
UFO 6TF UIF JOGPSNBUJPO UIF UZQF QSPWJEFT UP EFUFSNJOF XIBU
UIF GVODUJPO TIPVME EP 8FƊMM BMTP UFMM ZPV IPX NBOZ XBZT
UIFSF BSF UP XSJUF UIF GVODUJPO 4ZOUBDUJDBMMZ EJƵFSFOU CVU
TFNBOUJDBMMZ FRVJWBMFOU JNQMFNFOUBUJPOT BSF OPU DPVOUFE BT
CFJOH EJƵFSFOU 'PS FYBNQMF XSJUJOH B GVODUJPO POF XBZ UIFO
SFXSJUJOH UIF TFNBOUJDBMMZ JEFOUJDBM GVODUJPO CVU VTJOH BOPOZ
NPVT MBNCEB TZOUBY EPFT OPU DPVOU BT UXP JNQMFNFOUBUJPOT
5P NBLF UIJOHT B MJUUMF FBTJFS XFƊMM EFNPOTUSBUF IPX UP TPMWF
UIJT LJOE PG FYFSDJTF (JWFO
$)"15&3  5:1&4 

myFunc :: (x -> y)
-> (y -> z)
-> c
-> (a, x)
-> (a, z)
myFunc xToY yToZ _ (a, x) = undefined

5BMLJOH UISPVHI UIF BCPWF XF IBWF B GVODUJPO UIBU UBLFT


GPVS BSHVNFOUT 5IF ƶOBM SFTVMU JT B UVQMF XJUI UIF UZQF (a,
z) *U UVSOT PVU UIF Ԓ BSHVNFOU JT OPXIFSF JO PVS SFTVMUT BOE
UIFSFƊT OPUIJOH SFBMMZ UP EP XJUI JU TP XF VTF UIF VOEFSTDPSF
UP JHOPSF UIBU 8F OBNFE UIF UXP GVODUJPO BSHVNFOUT CZ UIFJS
UZQFT BOE QBUUFSO NBUDIFE PO UIF UVQMF BSHVNFOU 5IF POMZ
XBZ UP HFU UIF TFDPOE WBMVF PG UIF UVQMF GSPN UIF UZQF ԧ UP
UIF UZQF ԩ JT UP VTF CPUI PG UIF GVODUJPOT GVSOJTIFE UP VT *G XF
USJFE UIF GPMMPXJOH

myFunc xToY yToZ _ (a, x) =


(a, (xToY x))

8F XPVME HFU B UZQF FSSPS UIBU JU FYQFDUFE UIF UZQF ԩ CVU


UIF BDUVBM UZQF XBT Ԩ 5IBUƊT CFDBVTF XFƊSF PO UIF SJHIU QBUI
CVU OPU RVJUF EPOF ZFU "DDPSEJOHMZ UIF GPMMPXJOH TIPVME
UZQFDIFDL
$)"15&3  5:1&4 

myFunc :: (x -> y)
-> (y -> z)
-> c
-> (a, x)
-> (a, z)
myFunc xToY yToZ _ (a, x) =
(a, (yToZ (xToY x)))

 5IFSF JT POMZ POF GVODUJPO EFƶOJUJPO UIBU UZQFDIFDLT BOE


EPFTOƊU HP JOUP BO JOƶOJUF MPPQ XIFO ZPV SVO JU

i :: a -> a
i = undefined

 5IFSF JT POMZ POF WFSTJPO UIBU XPSLT

c :: a -> b -> a
c = undefined

 (JWFO BMQIB FRVJWBMFODF BSF c'' BOE c TFF BCPWF


UIF TBNF
UIJOH

c'' :: b -> a -> b


c'' = ?

 0OMZ POF WFSTJPO UIBU XPSLT

c' :: a -> b -> b


c' = undefined
$)"15&3  5:1&4 

 5IFSF BSF NVMUJQMF QPTTJCJMJUJFT BU MFBTU UXP PG XIJDI


ZPVƊWF TFFO JO QSFWJPVT DIBQUFST

r :: [a] -> [a]


r = undefined

 0OMZ POF WFSTJPO UIBU XJMM UZQFDIFDL

co :: (b -> c) -> (a -> b) -> a -> c


co = undefined

 0OF WFSTJPO XJMM UZQFDIFDL

a :: (a -> c) -> a -> a


a = undefined

 0OF WFSTJPO XJMM UZQFDIFDL

a' :: (a -> b) -> a -> b


a' = undefined

'JY JU
8POƊU TPNFPOF UBLF QJUZ PO UIJT QPPS CSPLFO DPEF BOE ƶY JU
VQ #F TVSF UP DIFDL DBSFGVMMZ GPS UIJOHT MJLF DBQJUBMJ[BUJPO
QBSFOUIFTFT BOE JOEFOUBUJPO

 module sing where


$)"15&3  5:1&4 

fstString :: [Char] ++ [Char]


fstString x = x ++ " in the rain"

sndString :: [Char] -> Char


sndString x = x ++ " over the rainbow"

sing = if (x > y) then fstString x or sndString y


where x = "Singin"
x = "Somewhere"

 /PX UIBU JUƊT ƶYFE NBLF B NJOPS DIBOHF BOE NBLF JU TJOH
UIF PUIFS TPOH *G ZPVƊSF MVDLZ ZPVƊMM FOE VQ XJUI CPUI
TPOHT TUVDL JO ZPVS IFBE

 -- arith3broken.hs
module Arith3Broken where

main :: IO ()
Main = do
print 1 + 2
putStrLn 10
print (negate -1)
print ((+) 0 blah)
where blah = negate 1
$)"15&3  5:1&4 

5ZQF,XPO%P
5IF OBNF JT DPVSUFTZ PG 1IJMMJQ 8SJHIU 5IBOL ZPV GPS UIF
JEFB
5IF GPDVT IFSF JT PO NBOJQVMBUJOH UFSNT JO PSEFS UP HFU UIF
UZQFT UP ƶU 5IJT TPSU PG FYFSDJTF JT TPNFUIJOH ZPVƊMM FODPVOUFS
JO XSJUJOH SFBM )BTLFMM DPEF TP UIF QSBDUJDF XJMM NBLF JU FBTJFS
UP EFBM XJUI XIFO ZPV HFU UIFSF 1SBDUJDJOH UIJT XJMM NBLF ZPV
CFUUFS BU XSJUJOH PSEJOBSZ DPEF BT XFMM
8F QSPWJEF UIF UZQFT BOE CPUUPNFE PVU EFDMBSFE BT undefined

UFSNT #PUUPN BOE VOEFƶOFE XJMM CF FYQMBJOFE JO NPSF EFUBJM


MBUFS 5IF DPOUFOUT PG UIF UFSNT BSF JSSFMFWBOU IFSF :PVƊMM VTF
POMZ UIF EFDMBSBUJPOT QSPWJEFE BOE XIBU UIF 1SFMVEF QSPWJEFT
CZ EFGBVMU VOMFTT PUIFSXJTF TQFDJƶFE :PVS HPBM JT UP NBLF UIF
???ƊE EFDMBSBUJPO QBTT UIF UZQFDIFDLFS CZ NPEJGZJOH JU BMPOF
)FSFƊT B XPSLFE FYBNQMF GPS IPX XF QSFTFOU UIFTF FYFSDJTFT
BOE IPX ZPV BSF FYQFDUFE UP TPMWF UIFN (JWFO UIF GPMMPXJOH

https://twitter.com/SixBitProxyWax
$)"15&3  5:1&4 

data Woot

data Blah

f :: Woot -> Blah


f = undefined

g :: (Blah, Woot) -> (Blah, Blah)


g = ???

)FSF JUƊT Ԗ UIBU ZPVƊSF TVQQPTFE UP JNQMFNFOU IPXFWFS


ZPV DBOƊU FWBMVBUF BOZUIJOH :PVƊSF UP POMZ VTF UZQFDIFDLJOH
BOE UZQFJOGFSFODF UP WBMJEBUF ZPVS BOTXFST "MTP OPUF UIBU
XFƊSF VTJOH B USJDL GPS EFƶOJOH EBUBUZQFT XIJDI DBO CF OBNFE
JO B UZQF TJHOBUVSF CVU IBWF OP WBMVFT )FSFƊT BO FYBNQMF PG
B WBMJE TPMVUJPO

g :: (Blah, Woot) -> (Blah, Blah)


g (b, w) = (b, f w)

5IF JEFB JT UP POMZ ƶMM JO XIBU XFƊWF NBSLFE XJUI ???


/PU BMM UFSNT XJMM BMXBZT CF VTFE JO UIF JOUFOEFE TPMVUJPO GPS B
QSPCMFN
$)"15&3  5:1&4 

 f :: Int -> String


f = undefined

g :: String -> Char


g = undefined

h :: Int -> Char


h = ???

 data A
data B
data C

q :: A -> B
q = undefined

w :: B -> C
w = undefined

e :: A -> C
e = ???
$)"15&3  5:1&4 

 data X
data Y
data Z

xz :: X -> Z
xz = undefined

yz :: Y -> Z
yz = undefined

xform :: (X, Y) -> (Z, Z)


xform = ???

 munge :: (x -> y) -> (y -> (w, z)) -> x -> w


munge = ???

 %FƶOJUJPOT
 1PMZNPSQIJTN SFGFST UP UZQF WBSJBCMFT XIJDI NBZ SFGFS UP
NPSF UIBO POF DPODSFUF UZQF *O )BTLFMM UIJT XJMM VTVBMMZ
NBOJGFTU BT QBSBNFUSJD PS BEIPD QPMZNPSQIJTN #Z IBW
JOH B MBSHFS TFU PG UZQFT XF JOUFSTFDU UIF DPNNPOBMJUJFT
PG UIFN BMM UP QSPEVDF B TNBMMFS TFU PG DPSSFDU UFSNT 5IJT
NBLFT JU MFTT MJLFMZ XFƊMM XSJUF BO JODPSSFDU QSPHSBN BOE
MFUT VT SFVTF UIF DPEF XJUI PUIFS UZQFT
$)"15&3  5:1&4 

 5ZQF JOGFSFODF JT B GBDVMUZ TPNF QSPHSBNNJOH MBOHVBHFT


NPTU OPUBCMZ )BTLFMM BOE .- IBWF UP JOGFS QSJODJQBM UZQFT
GSPN UFSNT XJUIPVU OFFEJOH FYQMJDJU UZQF BOOPUBUJPOT
5IFSF BSF JO TPNF DBTFT UFSNT JO )BTLFMM XIJDI DBO CF
XFMMUZQFE CVU XIJDI IBWF OP QSJODJQBM UZQF *O UIPTF
DBTFT BO FYQMJDJU UZQF BOOPUBUJPO NVTU CF BEEFE
8JUI SFTQFDU UP )BTLFMM UIF QSJODJQBM UZQF JT UIF NPTU
HFOFSJD UZQF XIJDI TUJMM UZQFDIFDLT .PSF HFOFSBMMZ 1SJO
DJQBM UZQF JT B QSPQFSUZ PG UIF UZQF TZTUFN ZPVƊSF JOUFSBDU
JOH XJUI 1SJODJQBM UZQJOH IPMET GPS UIBU UZQF TZTUFN JG B
UZQF DBO CF GPVOE GPS B UFSN JO BO FOWJSPONFOU GPS XIJDI
BMM PUIFS UZQFT GPS UIBU UFSN BSF JOTUBODFT PG UIF QSJODJQBM
UZQF )FSF BSF TPNF FYBNQMFT
$)"15&3  5:1&4 

-- Given the inferred types


a
Num a => a
Int

-- The principal type here is the


-- parametrically polymorphic 'a'.

-- Given these types


(Ord a, Num a) => a
Integer

-- The principal type is


-- (Ord a, Num a) => a

 5ZQF WBSJBCMF JT B XBZ UP SFGFS UP BO VOTQFDJƶFE UZQF PS


TFU PG UZQFT JO )BTLFMM UZQF TJHOBUVSFT 5ZQF WBSJBCMFT
PSEJOBSJMZ XJMM CF FRVBM UP UIFNTFMWFT UISPVHIPVU B UZQF
TJHOBUVSF -FU VT DPOTJEFS TPNF FYBNQMFT
$)"15&3  5:1&4 

id :: a -> a

-- One type variable 'a' that occurs twice,


-- once as an argument, once as a result.
-- Parametrically polymorphic, could be
-- strictly anything

(+) :: Num a => a -> a -> a

-- One type variable 'a', constrained to needing


-- an instance of Num. Two arguments, one result.
-- All the same type.

 " UZQFDMBTT JT B NFBOT PG FYQSFTTJOH GBDVMUJFT PS JOUFSGBDFT


UIBU NVMUJQMF EBUBUZQFT NBZ IBWF JO DPNNPO 5IJT FO
BCMFT VT UP XSJUF DPEF FYDMVTJWFMZ JO UFSNT PG UIPTF DPN
NPOBMJUJFT XJUIPVU SFQFBUJOH ZPVSTFMG GPS FBDI JOTUBODF
+VTU BT POF NBZ TVN WBMVFT PG UZQF Int Integer Float
Double BOE Rational XF DBO BWPJE IBWJOH EJƵFSFOU (+) (*)
(-) negate FUD GVODUJPOT GPS FBDI CZ VOJGZJOH UIFN JOUP
B TJOHMF UZQFDMBTT *NQPSUBOUMZ UIFTF DBO UIFO CF VTFE
XJUI BMM UZQFT UIBU IBWF B Num JOTUBODF 5IVT B UZQFDMBTT
QSPWJEFT VT B NFBOT UP XSJUF DPEF JO UFSNT PG UIPTF PQFS
BUPST BOE IBWF PVS GVODUJPOT CF DPNQBUJCMF XJUI BMM UZQFT
UIBU IBWF JOTUBODFT PG UIBU UZQFDMBTT XIFUIFS UIFZ BMSFBEZ
$)"15&3  5:1&4 

FYJTU PS BSF ZFU UP CF JOWFOUFE CZ ZPV QFSIBQT




 1BSBNFUSJDJUZ JT UIF QSPQFSUZ UIBU IPMET JO UIF QSFTFODF PG


QBSBNFUSJD QPMZNPSQIJTN 1BSBNFUSJDJUZ TUBUFT UIBU UIF
CFIBWJPS PG B GVODUJPO XJMM CF VOJGPSN BDSPTT BMM DPODSFUF
BQQMJDBUJPOT PG UIF GVODUJPO 1BSBNFUSJDJUZ UFMMT VT UIBU
UIF GVODUJPO

id :: a -> a

$BO CF VOEFSTUPPE UP IBWF UIF TBNF FYBDU CFIBWJPS GPS


FWFSZ UZQF JO )BTLFMM XJUIPVU VT OFFEJOH UP TFF IPX JU
XBT XSJUUFO *U JT UIF TBNF QSPQFSUZ UIBU UFMMT VT

const :: a -> b -> a

const NVTU SFUVSO UIF ƶSTU WBMVF ƈ QBSBNFUSJDJUZ BOE UIF


EFƶOJUJPO PG UIF UZQF SFRVJSFT JU

f :: a -> a -> a

)FSF ԕ DBO POMZ SFUVSO UIF ƶSTU PS TFDPOE WBMVF OPUIJOH


FMTF BOE JU XJMM BMXBZT SFUVSO POF PS UIF PUIFS DPOTJTUFOUMZ
XJUIPVU DIBOHJOH *G UIF GVODUJPO ԕ NBEF VTF PG (+) PS
(*) JUT UZQF XPVME OFDFTTBSJMZ CF DPOTUSBJOFE CZ UIF UZQF
DMBTT /VN BOE UIVT CF BO FYBNQMF PG BEIPD SBUIFS UIBO
QBSBNFUSJD QPMZNPSQIJTN

&YBNQMFT BSF DPVSUFTZ PG UIF @parametricity UXJUUFS BDDPVOU
https://twitter.com/parametricity
$)"15&3  5:1&4 

blahFunc :: b -> String

blahFunc UPUBMMZ JHOPSFT JUT BSHVNFOU BOE JT FƵFDUJWFMZ B


DPOTUBOU WBMVF PG UZQF 4USJOH XIJDI SFRVJSFT B UISPXBXBZ
BSHVNFOU GPS OP SFBTPO

convList :: a -> [a]

6OMFTT UIF SFTVMU JT [] UIF SFTVMUJOH MJTU IBT WBMVFT UIBU BSF
BMM UIF TBNF WBMVF 5IF MJTU XJMM BMXBZT CF UIF TBNF MFOHUI

 "EIPD QPMZNPSQIJTN TPNFUJNFT DBMMFE ƌDPOTUSBJOFE QPMZ


NPSQIJTNƍ
JT QPMZNPSQIJTN UIBU BQQMJFT POF PS NPSF
UZQFDMBTT DPOTUSBJOUT UP XIBU XPVMEƊWF PUIFSXJTF CFFO B
QBSBNFUSJDBMMZ QPMZNPSQIJD UZQF WBSJBCMF )FSF SBUIFS
UIBO SFQSFTFOUJOH B VOJGPSNJUZ PG CFIBWJPS BDSPTT BMM DPO
DSFUF BQQMJDBUJPOT UIF QVSQPTF PG BEIPD QPMZNPSQIJTN
JT UP BMMPX UIF GVODUJPOT UP IBWF EJƵFSFOU CFIBWJPS GPS FBDI
JOTUBODF 5IJT BEIPDOFTT JT DPOTUSBJOFE CZ UIF UZQFT
JO UIF UZQFDMBTT UIBU EFƶOFT UIF NFUIPET BOE )BTLFMMƊT
SFRVJSFNFOU UIBU UZQFDMBTT JOTUBODFT CF VOJRVF GPS B HJWFO
UZQF 'PS BOZ HJWFO DPNCJOBUJPO PG UZQFDMBTT BOE B UZQF
TVDI BT Ord BOE Bool UIFSF NVTU POMZ FYJTU POF VOJRVF
JOTUBODF JO TDPQF 5IJT NBLFT JU DPOTJEFSBCMZ FBTJFS UP
SFBTPO BCPVU UZQFDMBTTFT 4FF UIF FYBNQMF GPS B EJTBN
CJHVBUJPO
$)"15&3  5:1&4 

(+) :: Num a => a -> a -> a

-- the above function is leveraging


-- ad-hoc polymorphism via the Num typeclass

c' :: a -> a -> a

-- This function is not,


-- it's parametrically polymorphic in 'a'.

 " NPEVMF JT UIF VOJU PG PSHBOJ[BUJPO UIBU UIF )BTLFMM QSP


HSBNNJOH MBOHVBHF VTFT UP DPMMFDU UPHFUIFS EFDMBSBUJPOT
PG WBMVFT GVODUJPOT EBUB UZQFT UZQFDMBTTFT BOE UZQFDMBTT
JOTUBODFT "OZ UJNF ZPV VTF ƌJNQPSUƍ JO )BTLFMM ZPV BSF
JNQPSUJOH EFDMBSBUJPOT GSPN B NPEVMF -FU VT MPPL BU BO
FYBNQMF GSPN UIF DIBQUFS FYFSDJTFT

{-# LANGUAGE NoMonomorphismRestriction #-}

module DetermineTheType where


-- ^ name of our module

)FSF XF NBEF PVS )BTLFMM TPVSDF ƶMF IBWF B NPEVMF BOE


XF OBNFE JU DetermineTheType 8F JODMVEFE B EJSFDUJWF UP
UIF DPNQJMFS UP EJTBCMF UIF NPOPNPSQIJTN SFTUSJDUJPO
$)"15&3  5:1&4 

CFGPSF XF EFDMBSFE UIF NPEVMF "MTP DPOTJEFS UIF GPMMPX


JOH FYBNQMF VTJOH import

import Data.Aeson (encode)


-- ^ the module Data.Aeson
import Database.Persist
-- ^ the module Database.Persist

*O UIF BCPWF FYBNQMF XF BSF JNQPSUJOH UIF GVODUJPO


encode EFDMBSFE JO UIF NPEVMF Data.Aeson BMPOH XJUI BOZ
UZQFDMBTT JOTUBODFT 8JUI UIF NPEVMF Database.Persist XF
BSF JNQPSUJOH FWFSZUIJOH JU NBLFT BWBJMBCMF

 'PMMPXVQ SFTPVSDFT


 -VJT %BNBT 3PCJO .JMOFS 1SJODJQBM UZQFTDIFNFT GPS
GVODUJPOBM QSPHSBNT

 $ISJTUPQIFS 4USBDIFZ 'VOEBNFOUBM $PODFQUT JO 1SP


HSBNNJOH -BOHVBHFT
1PQVMBS PSJHJO PG UIF QBSBNFUSJDBEIPD QPMZNPSQIJTN
EJTUJODUJPO
$IBQUFS 

5ZQFDMBTTFT

" CMBOL DIFRVF LJMMT


DSFBUJWJUZ

.PLPLPNB .PLIPOPBOB


$)"15&3  -&44 "%)0$ 10-:.031)*4. 

 5ZQFDMBTTFT
:PV NBZ IBWF SFBMJ[FE UIBU JU JT WFSZ EJƸDVMU UP UBML BCPVU PS
VOEFSTUBOE )BTLFMMƊT UZQF TZTUFN XJUIPVU BMTP UBMLJOH BCPVU
UZQFDMBTTFT 4P GBS XFƊWF CFFO GPDVTFE PO UIF XBZ UIFZ JOUFSBDU
XJUI UZQF WBSJBCMFT BOE OVNFSJD UZQFT FTQFDJBMMZ 5IJT DIBQUFS
FYQMBJOT TPNF JNQPSUBOU QSFEFƶOFE UZQFDMBTTFT POMZ TPNF
PG XIJDI IBWF UP EP XJUI OVNCFST BOE QSPWJEFT NPSF EFUBJM
BCPVU IPX UZQFDMBTTFT XPSL NPSF HFOFSBMMZ *O UIJT DIBQUFS
XF XJMM

Ƒ FYBNJOF UIF UZQFDMBTTFT Eq Num Ord Enum BOE Show

Ƒ MFBSO BCPVU UZQFEFGBVMUJOH UZQFDMBTTFT BOE UZQFDMBTT JO


IFSJUBODF

Ƒ MPPL BU TPNF DPNNPO CVU PǒFO JNQMJDJU GVODUJPOT UIBU


DSFBUF TJEF FƵFDUT

 8IBU BSF UZQFDMBTTFT


5ZQFDMBTTFT BOE UZQFT JO )BTLFMM BSF JO B TFOTF PQQPTJUFT
8IFSF B EFDMBSBUJPO PG B UZQF EFƶOFT IPX UIBU UZQF JO QBSUJD
VMBS JT DSFBUFE B EFDMBSBUJPO PG B UZQFDMBTT EFƶOFT IPX B TFU
PG UZQFT BSF DPOTVNFE PS VTFE JO DPNQVUBUJPOT 5IJT UFOTJPO
JT SFMBUFE UP UIF FYQSFTTJPO QSPCMFN XIJDI JT BCPVU EFƶOJOH
DPEF JO UFSNT PG IPX EBUB JT DSFBUFE PS QSPDFTTFE "T 1IJMJQ
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

8BEMFS QVU JU ƌ5IF HPBM JT UP EFƶOF B EBUBUZQF CZ DBTFT XIFSF


POF DBO BEE OFX DBTFT UP UIF EBUBUZQF BOE OFX GVODUJPOT PWFS
UIF EBUBUZQF XJUIPVU SFDPNQJMJOH FYJTUJOH DPEF BOE XIJMF
SFUBJOJOH TUBUJD UZQF TBGFUZ FH OP DBTUT
ƍ *G ZPV LOPX PUIFS
QSPHSBNNJOH MBOHVBHFT XJUI B TJNJMBS DPODFQU JU NBZ IFMQ UP
UIJOL PG UZQFDMBTTFT BT CFJOH MJLF JOUFSGBDFT UP EBUB UIBU DBO XPSL
BDSPTT NVMUJQMF EBUBUZQFT 5IF MBUUFS GBDJMJUZ JT XIZ UZQFDMBTTFT
BSF B NFBOT PG BE IPD QPMZNPSQIJTN ƈ ƌBE IPDƍ CFDBVTF UZQF
DMBTT DPEF JT EJTQBUDIFE CZ UZQF TPNFUIJOH XF XJMM FYQMBJO
MBUFS JO UIJT DIBQUFS 8F XJMM DPOUJOVF DBMMJOH JU DPOTUSBJOFE
QPMZNPSQIJTN UIPVHI BT XF UIJOL UIBU UFSN JT HFOFSBMMZ
NPSF DMFBS
5ZQFDMBTTFT BMMPX VT UP HFOFSBMJ[F PWFS B TFU PG UZQFT JO
PSEFS UP EFƶOF BOE FYFDVUF B TUBOEBSE TFU PG GFBUVSFT GPS UIPTF
UZQFT 'PS FYBNQMF UIF BCJMJUZ UP UFTU WBMVFT GPS FRVBMJUZ JT
VTFGVM BOE XFƊE XBOU UP CF BCMF UP VTF UIBU GVODUJPO GPS EBUB
PG WBSJPVT UZQFT *O GBDU XF DBO UFTU BOZ EBUB PG B UZQF UIBU
JNQMFNFOUT UIF UZQFDMBTT LOPXO BT Eq GPS FRVBMJUZ 8F EP
OPU OFFE TFQBSBUF FRVBMJUZ GVODUJPOT GPS FBDI EJƵFSFOU UZQF
PG EBUB BT MPOH BT PVS EBUBUZQF JNQMFNFOUT PS JOTUBOUJBUFT
UIF Eq UZQFDMBTT XF DBO VTF UIF TUBOEBSE GVODUJPOT 4JNJMBSMZ
BMM UIF OVNFSJD MJUFSBMT BOE UIFJS WBSJPVT UZQFT JNQMFNFOU B
UZQFDMBTT DBMMFE Num XIJDI EFƶOFT B TUBOEBSE TFU PG PQFSBUPST
UIBU DBO CF VTFE XJUI BOZ UZQF PG OVNCFST

1IJMJQ 8BEMFS ƌ5IF &YQSFTTJPO 1SPCMFNƍ http://homepages.inf.ed.ac.uk/wadler/
papers/expression/expression.txt
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

8FƊMM HFU JOUP NPSF EFUBJM BCPVU XIBU JU NFBOT GPS B UZQF
UP IBWF BO ƌJOTUBODFƍ PG B UZQFDMBTT JO UIJT DIBQUFS CVU CSJFƷZ
TUBUFE JU NFBOT UIBU UIFSF JT DPEF UIBU EFƶOFT IPX UIF WBMVFT
BOE GVODUJPOT GSPN UIBU UZQFDMBTT XPSL GPS UIBU UZQF 8IFO
ZPV VTF B UZQFDMBTT NFUIPE XJUI POF PG UIF UZQFT UIBU IBT TVDI
BO JOTUBODF UIF DPNQJMFS MPPLT VQ UIF DPEF UIBU EJDUBUFT IPX
UIF GVODUJPO XPSLT GPS UIBU UZQF 8FƊMM TFF UIJT NPSF BT XF
XSJUF PVS PXO JOTUBODFT

 #BDL UP #PPM


-FUƊT SFUVSO CSJFƷZ UP UIF Bool UZQF UP HFU B GFFM GPS XIBU UZQF
DMBTT JOGPSNBUJPO SFBMMZ MPPLT MJLF "T ZPV NBZ SFDBMM XF DBO
VTF UIF ()$J DPNNBOE :info UP RVFSZ JOGPSNBUJPO JODMVEJOH
UZQFDMBTT JOGPSNBUJPO BCPVU BOZ GVODUJPO PS UZQF BOE TPNF
WBMVFT


Prelude> :info Bool


data Bool = False | True
instance Bounded Bool
instance Enum Bool
instance Eq Bool
instance Ord Bool
instance Read Bool
instance Show Bool
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

5IF JOGPSNBUJPO JODMVEFT UIF EBUB EFDMBSBUJPO GPS Bool BOE


XIJDI UZQFDMBTTFT JU BMSFBEZ IBT JOTUBODFT PG *U BMTP UFMMT ZPV
XIFSF UIF EBUBUZQF BOE JUT JOTUBODFT BSF EFƶOFE GPS UIF DPN
QJMFS JG ZPV XBOU UP MPPL BU UIF TPVSDF DPEF CVU XFƊWF MFǒ UIBU
JOGPSNBUJPO PVU
-FUƊT MPPL BU UIBU MJTU PG JOTUBODFT &BDI PG UIFTF JOTUBODFT
JT B UZQFDMBTT UIBU Bool JNQMFNFOUT BOE UIF JOTUBODFT BSF UIF
VOJRVF TQFDJƶDBUJPOT PG IPX Bool NBLFT VTF PG UIF NFUIPET
GSPN UIBU UZQFDMBTT *O UIJT DIBQUFS XFƊSF POMZ HPJOH UP FYBN
JOF B GFX PG UIFTF OBNFMZ Eq Ord BOE Show #SJFƷZ IPXFWFS
UIFZ NFBO UIF GPMMPXJOH

 instance Bounded Bool Ƈ Bounded GPS UZQFT UIBU IBWF BO VQ


QFS BOE MPXFS CPVOE

 instance Enum Bool Ƈ Enum GPS UIJOHT UIBU DBO CF FOVNFS


BUFE

 instance Eq Bool Ƈ Eq GPS UIJOHT UIBU DBO CF UFTUFE GPS FRVBM


JUZ

 instance Ord Bool Ƈ Ord GPS UIJOHT UIBU DBO CF QVU JOUP B
TFRVFOUJBM PSEFS

 instance Read Bool Ƈ Read QBSTFT TUSJOHT JOUP UIJOHT %POƊU


VTF JU /P TFSJPVTMZ EPOƊU

 instance Show Bool Ƈ Show SFOEFST UIJOHT JOUP TUSJOHT


$)"15&3  -&44 "%)0$ 10-:.031)*4. 

5ZQFDMBTTFT IBWF B IJFSBSDIZ PG TPSUT  BT ZPV NJHIU SFDBMM


GSPN PVS EJTDVTTJPO PG OVNFSJD UZQFT "MM Fractional OVNCFST
JNQMFNFOU UIF Num UZQFDMBTT CVU OPU BMM Num BSF Fractional "MM
NFNCFST PG Ord NVTU CF NFNCFST PG Eq BOE BMM NFNCFST PG
Enum NVTU CF NFNCFST PG Ord 5P CF BCMF UP QVU TPNFUIJOH
JO BO FOVNFSBUFE MJTU UIFZ NVTU CF BCMF UP CF PSEFSFE UP CF
BCMF UP PSEFS TPNFUIJOH UIFZ NVTU CF BCMF UP CF DPNQBSFE
GPS FRVBMJUZ

 &R
*O )BTLFMM FRVBMJUZ JT JNQMFNFOUFE XJUI B UZQFDMBTT DBMMFE Eq
4PNF QSPHSBNNJOH MBOHVBHFT CBLF FRVBMJUZ JOUP FWFSZ PCKFDU
JO UIF MBOHVBHF CVU TPNF EBUBUZQFT EP OPU IBWF B TFOTJCMF
OPUJPO PG FRVBMJUZ TP )BTLFMM EPFT OPU FODPEF FRVBMJUZ JOUP
FWFSZ UZQF Eq BMMPXT VT UP VTF TUBOEBSE NFBTVSFT PG FRVBMJUZ
GPS RVJUF B GFX EBUBUZQFT UIPVHI
Eq JT EFƶOFE UIJT XBZ

Prelude> :info Eq
class Eq a where
(==) :: a -> a -> Bool

:PV DBO VTF B TFBSDI FOHJOF MJLF )PPHMF BU http://haskell.org/hoogle UP ƶOE JOGPSNB
UJPO PO )BTLFMM EBUBUZQFT BOE UZQFDMBTTFT )PPHMF JT B )BTLFMM "1* TFBSDI FOHJOF XIJDI
BMMPXT ZPV UP TFBSDI NBOZ TUBOEBSE )BTLFMM MJCSBSJFT CZ GVODUJPO OBNF PS UZQF TJHOBUVSF
"T ZPV CFDPNF ƷVFOU JO )BTLFMM UZQFT ZPV XJMM CF BCMF UP JOQVU UIF UZQF PG UIF GVODUJPO
ZPV XBOU BOE ƶOE UIF GVODUJPOT UIBU NBUDI

.PTU JNQPSUBOUMZ UIF GVODUJPO UZQF EPFT OPU IBWF BO Eq JOTUBODF GPS SFBTPOT XF XJMM
OPU HFU JOUP IFSF
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

(/=) :: a -> a -> Bool

'JSTU JU UFMMT VT XF IBWF B UZQFDMBTT DBMMFE Eq XIFSF UIFSF BSF


UXP CBTJD GVODUJPOT FRVBMJUZ BOE OPOFRVBMJUZ BOE HJWFT UIFJS
UZQF TJHOBUVSFT /FYU JU MJTUT UIF JOTUBODFT PG Eq

-- partial list
instance Eq a => Eq [a]
instance Eq Ordering
instance Eq Int
instance Eq Float
instance Eq Double
instance Eq Char
instance Eq Bool
instance (Eq a, Eq b) => Eq (a, b)
instance Eq ()
instance Eq a => Eq (Maybe a)
instance Eq Integer

8F TFF TFWFSBM OVNFSJD UZQFT PVS PME GSJFOE Bool Char VO
TVSQSJTJOH BT XFƊWF TFFO UIBU XF DBO DPNQBSF DIBSBDUFST GPS
FRVBMJUZ
BOE UVQMFT 8F LOPX GSPN UIJT UIBU BOZ UJNF XF BSF
VTJOH EBUB PG UIFTF UZQFT XF BSF JNQMFNFOUJOH UIF Eq UZQFDMBTT
BOE UIFSFGPSF IBWF HFOFSJD GVODUJPOT XF DBO VTF UP DPNQBSF
UIFJS FRVBMJUZ "OZ UZQF UIBU IBT BO JOTUBODF PG UIJT UZQFDMBTT
JNQMFNFOUT UIF NFUIPET PG UIF UZQFDMBTT
)FSF BSF TPNF FYBNQMFT VTJOH UIJT UZQFDMBTT
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

Prelude> 132 == 132


True
Prelude> 132 /= 132
False
Prelude> (1, 2) == (1, 1)
False
Prelude> (1, 1) == (1, 2)
False
Prelude> "doge" == "doge"
True
Prelude> "doge" == "doggie"
False

5IF UZQFT PG (==) BOE (/=) JO Eq UFMM VT TPNFUIJOH JNQPSUBOU


BCPVU UIFTF GVODUJPOT

(==) :: Eq a => a -> a -> Bool


(/=) :: Eq a => a -> a -> Bool

(JWFO UIFTF UZQFT XF LOPX UIBU UIFZ DBO CF VTFE GPS BOZ
UZQF Ԑ XIJDI JNQMFNFOUT UIF Eq UZQFDMBTT 8F BMTP LOPX UIBU
CPUI GVODUJPOT XJMM UBLF UXP BSHVNFOUT PG UIF TBNF UZQF Ԑ BOE
SFUVSO Bool 8F LOPX UIFZ IBWF UP CF UIF TBNF CFDBVTF Ԑ NVTU
FRVBM Ԑ JO UIF TBNF UZQF TJHOBUVSF
8IFO XF BQQMZ (==) UP B TJOHMF BSHVNFOU XF DBO TFF IPX
JU TQFDJBMJ[FT UIF BSHVNFOUT
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

(==) :: Eq a => a -> a -> Bool


-- if we specialized (==) for [Char] aka String
(==) :: [Char] -> [Char] -> Bool
(==) "cat" :: [Char] -> Bool
(==) "cat" "cat" :: Bool

:PV DBO FYQFSJNFOU XJUI UIJT GVSUIFS JO UIF 3&1- UP TFF


IPX BQQMZJOH UZQFT UP BSHVNFOUT NBLFT UIF UZQF WBSJBCMFT
NPSF TQFDJƶD
8IBU IBQQFOT JG UIF ƶSTU UXP BSHVNFOUT Ԑ BOE Ԑ BSFOƊU UIF
TBNF UZQF

Prelude F M> (1, 2) == "puppies!"

Couldn't match expected type ‘(t0, t1)’


with actual type ‘[Char]’
In the second argument of ‘(==)’, namely ‘"puppies!"’
In the expression: (1, 2) == "puppies!"
In an equation for ‘it’: it = (1, 2) == "puppies!"

-FUƊT CSFBL EPXO UIJT UZQF FSSPS

Couldn't match expected type ‘(t0, t1)’


with actual type ‘[Char]’

5IJT FSSPS NFBOT PVS [Char] XBTOƊU UIF UVQMF PG UZQFT ԣ BOE
ԣ UIBU XBT FYQFDUFE (t0, t1) XBT FYQFDUFE GPS UIF TFDPOE
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

BSHVNFOU XIFSF XF TVQQMJFE "puppies!"


CFDBVTF UIBUƊT UIF
UZQF PG UIF ƶSTU BSHVNFOU 3FNFNCFS UIF UZQF PG Ԑ JT VTVBMMZ
TFU CZ UIF MFǒNPTU PDDVSSFODF BOE DBOƊU DIBOHF JO UIF TJHOBUVSF
Eq a => a -> a -> Bool
"QQMZJOH (==) UP Integer XJMM CJOE UIF Ԑ UZQF WBSJBCMF UP
Integer 5IJT JT BT JG UIF TJHOBUVSF DIBOHFE UP

Eq Integer => Integer -> Integer -> Bool

5IF UZQFDMBTT DPOTUSBJOU Eq Integer => HFUT ESPQQFE CFDBVTF


JUƊT SFEVOEBOU 8F DBO TFF UIF JTTVF NPSF DMFBSMZ JG XF MPPL BU
UIF UZQFDMBTT JOTUBODFT PO UIF UVQMF (,)

data (,) a b = (,) a b


instance (Eq a, Eq b) => Eq (a, b)
instance (Ord a, Ord b) => Ord (a, b)
instance (Read a, Read b) => Read (a, b)
instance (Show a, Show b) => Show (a, b)

8F TBX UIF Eq JOTUBODF PG (,) HFUUJOH VTFE FBSMJFS XIFO XF


UFTUFE DPEF MJLF (1, 2) == (1, 2) $SJUJDBMMZ UIF Eq JOTUBODF PG
(a, b) SFMJFT PO UIF Eq JOTUBODFT PG Ԑ BOE ԑ 5IJT UFMMT VT UIF
FRVBMJUZ PG UXP UVQMFT (a, b) EFQFOET PO UIF FRVBMJUZ PG UIFJS
DPOTUJUVFOU WBMVFT Ԑ BOE ԑ 5IJT JT XIZ UIJT XPSLT

Prelude> (1, 'a') == (2, 'b')


False
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

#VU OFJUIFS PG UIFTF XJMM XPSL

Prelude> (1, 2) == ('a', 'b')

Prelude> (1, 'a') == ('a', 1)

5ZQFDMBTT EFSJWJOH 5ZQFDMBTT JOTUBODFT XF DBO NBHJDBMMZ EF


SJWF BSF Eq Ord Enum Bounded Read BOE Show UIPVHI UIFSF BSF
TPNF DPOTUSBJOUT PO EFSJWJOH TPNF PG UIFTF %FSJWJOH NFBOT
ZPV EPOƊU IBWF UP NBOVBMMZ XSJUF JOTUBODFT PG UIFTF UZQFDMBTTFT
GPS FBDI OFX EBUBUZQF ZPV DSFBUF 8FƊMM BEESFTT UIJT B CJU NPSF
JO UIF DIBQUFS PO "MHFCSBJD %BUBUZQFT

 8SJUJOH UZQFDMBTT JOTUBODFT


8F IBWFOƊU UBMLFE NVDI BCPVU XSJUJOH ZPVS PXO EBUBUZQFT ZFU
CVU XFƊMM MPPL BU JU JO HSFBU EFUBJM JO B MBUFS DIBQUFS :PV DBO
BMTP XSJUF ZPVS PXO UZQFDMBTT XIJDI XF XJMM MPPL BU MBUFS JO
UIJT DIBQUFS *O FJUIFS DBTF ZPV XJMM TPNFUJNFT ƶOE ZPVSTFMG
OFFEJOH UP XSJUF ZPVS PXO UZQFDMBTT JOTUBODFT 8IJMF Eq JT POF
PG UIF UZQFDMBTTFT ZPV DBO TJNQMZ EFSJWF JUƊT BMTP POF PG UIF
MFBTU DPNQMJDBUFE UZQFDMBTTFT UP XSJUF JOTUBODFT GPS TP XFƊSF
HPJOH UP VTF JU IFSF UP EFNPOTUSBUF IPX UP XSJUF ZPVS PXO
JOTUBODFT
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

&R JOTUBODFT
"T XFƊWF TFFO Eq QSPWJEFT JOTUBODFT GPS EFUFSNJOJOH FRVBMJUZ
PG WBMVFT TP NBLJOH BO JOTUBODF PG JU GPS B HJWFO EBUBUZQF JT
VTVBMMZ TUSBJHIUGPSXBSE
:PV DBO JOWFTUJHBUF B UZQFDMBTT CZ SFGFSSJOH UP UIF )BDL
BHF EPDVNFOUBUJPO GPS UIBU UZQFDMBTT 5ZQFDMBTTFT MJLF Eq
DPNF XJUI UIF DPSF base MJCSBSZ UIBU JT MPDBUFE BU http://hackage.
haskell.org/package/base  Eq TQFDJƶDBMMZ JT MPDBUFE BU http://
hackage.haskell.org/package/base/docs/Data-Eq.html
*O UIBU EPDVNFOUBUJPO ZPVƊMM XBOU UP OPUF B QBSUJDVMBS CJU
PG XPSEJOH

Minimal complete definition: either == or /=.

5IJT UFMMT ZPV XIBU NFUIPET ZPV OFFE UP EFƶOF UP IBWF


B WBMJE Eq JOTUBODF *O UIJT DBTF FJUIFS (==) FRVBM
PS (/=)
VOFRVBM
XJMM TVƸDF BT POF DBO CF EFƶOFE BT UIF OFHBUJPO PG
UIF PUIFS 8IZ OPU POMZ (==) "MUIPVHI JUƊT SBSF ZPV NBZ IBWF
TPNFUIJOH DMFWFS UP EP GPS FBDI DBTF UIBU DPVME NBLF FRVBMJUZ
DIFDLJOH GBTUFS GPS B QBSUJDVMBS EBUBUZQF TP ZPVƊSF BMMPXFE UP
TQFDJGZ CPUI JG ZPV XBOU UP 8F XPOƊU EP UIBU IFSF CFDBVTF
(/=) JT KVTU UIF OFHBUJPO PG (==) BOE XF XPOƊU CF XPSLJOH XJUI
BOZ DMFWFS EBUBUZQFT
'JSTU XFƊMM XPSL XJUI B UJOZ USJWJBM EBUBUZQF DBMMFETrivial
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

data Trivial =
Trivial

8JUI OP deriving DMBVTF IBOHJOH PƵ UIF CVUU PG UIJT EBUBUZQF


EFDMBSBUJPO XFƊMM IBWF OP UZQFDMBTT JOTUBODFT PG BOZ LJOE *G XF
USZ UP MPBE UIJT VQ BOE UFTU FRVBMJUZ XJUIPVU BEEJOH BOZUIJOH
GVSUIFS ()$ XJMM UISPX B UZQF FSSPS

Prelude> Trivial == Trivial

No instance for (Eq Trivial) arising


from a use of ‘==’
In the expression: Trivial == Trivial
In an equation for ‘it’: it = Trivial == Trivial

()$ DBOƊU ƶOE BO JOTUBODF PG Eq GPS PVS EBUBUZQF Trivial


8F DPVMEƊWF IBE ()$ HFOFSBUF POF GPS VT VTJOH deriving Eq
PS XF DPVMEƊWF XSJUUFO POF CVU XF EJE OFJUIFS TP OPOF FYJTUT
BOE JU GBJMT BU DPNQJMF UJNF *O TPNF MBOHVBHFT UIJT TPSU PG
NJTUBLF EPFTOƊU CFDPNF LOPXO VOUJM ZPVS DPEF JT BMSFBEZ JO
UIF NJEEMF PG FYFDVUJOH
6OMJLF PUIFS MBOHVBHFT )BTLFMM EPFT OPU QSPWJEF VOJWFSTBM
TUSJOHJƶDBUJPO Show  QSJOU
PS FRVBMJUZ Eq WBMVF FRVBMJUZ
PS
QPJOUFS FRVBMJUZ
BT UIJT JT OPU BMXBZT TPVOE PS TBGF SFHBSEMFTT
PG XIBU QSPHSBNNJOH MBOHVBHF ZPVƊSF VTJOH
4P XF NVTU XSJUF PVS PXO 'PSUVOBUFMZ XJUI Trivial UIJT
JTUSJWJBM
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

-- keep your typeclass instances for a type


-- in the same file as that type
-- we'll explain why later

data Trivial =
Trivial'

instance Eq Trivial where


Trivial' == Trivial' = True

"OE UIBUƊT JU 8F XSPUF BO JOTUBODF UIBU UFMMT UIF DPNQJMFS


IPX UP UFTU UIJT EBUBUZQF GPS FRVBMJUZ %BUB DPOTUSVDUPST BOE
UZQF DPOTUSVDUPST PǒFO IBWF UIF TBNF OBNF JO )BTLFMM BOE
UIBU DBO HFU DPOGVTJOH 8F VTFE UIF TJOHMF RVPUF BU UIF FOE PG
UIF EBUB DPOTUSVDUPS IFSF CFDBVTF UIFZ EPOƊU IBWF UP IBWF UIF
TBNF OBNF BOE JU NJHIU NBLF JU FBTJFS UP GPMMPX UIF FYBNQMFT

*G ZPV MPBE UIJT VQ ZPV IBWF POMZ POF QPTTJCMF FYQSFTTJPO


ZPV DBO DPOTUSVDU IFSF

Prelude> Trivial' == Trivial'


True

-FUƊT ESJMM EPXO B CJU JOUP IPX UIJT JOTUBODF TUVƵ XPSLT
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

instance Eq Trivial where


-- [1] [2] [3] [4]
Trivial' == Trivial' = True
-- [5] [6] [7] [8]

instance Eq Trivial where


(==) Trivial' Trivial' = True
-- [ 9 ]

 5IF LFZXPSE instance IFSF CFHJOT B EFDMBSBUJPO PG B UZQF


DMBTT JOTUBODF 5ZQFDMBTT JOTUBODFT BSF IPX ZPV UFMM )BTLFMM
IPX FRVBMJUZ TUSJOHJƶDBUJPO 4IPX
PSEFSBCJMJUZ 0SE

FOVNFSBUJPO &OVN
PS PUIFS UZQFDMBTTFT TIPVME XPSL
GPS B QBSUJDVMBS EBUBUZQF 8JUIPVU UIJT JOTUBODF XF DBOƊU
UFTU UIF WBMVFT GPS FRVBMJUZ FWFO UIPVHI UIF BOTXFS XJMM
OFWFS WBSZ JO UIF DBTF PG UIJT QBSUJDVMBS EBUBUZQF

 5IF ƶSTU OBNF UP GPMMPX UIF instance JT UIF UZQFDMBTT UIF


JOTUBODF JT QSPWJEJOH )FSF UIBU JT Eq

 5IF UZQF UIF JOTUBODF JT CFJOH QSPWJEFE GPS *O UIJT DBTF


XFƊSF JNQMFNFOUJOH UIF Eq UZQFDMBTT GPS UIF Trivial EBUBUZQF

 5IF LFZXPSE where UFSNJOBUFT UIF JOJUJBM EFDMBSBUJPO BOE


CFHJOOJOH PG UIF JOTUBODF 8IBU GPMMPXT BSF UIF BDUVBM
NFUIPET GVODUJPOT
CFJOH JNQMFNFOUFE
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

 5IF EBUB DPOTUSVDUPS WBMVF


Trivial' JT UIF ƶSTU BSHVNFOU
UP UIF == GVODUJPO XFƊSF QSPWJEJOH )FSF XFƊSF EFƶOJOH ==
VTJOH JOƶY OPUBUJPO TP UIF ƶSTU BSHVNFOU JT UP UIF MFǒ

 5IF JOƶY GVODUJPO == UIJT JT XIBU XFƊSF EFƶOJOH JO UIJT


EFDMBSBUJPO

 5IF TFDPOE BSHVNFOU XIJDI JT UIF WBMVF Trivial' 4JODF


== JT JOƶY IFSF UIF TFDPOE BSHVNFOU JT UP UIF SJHIU PG ==

 5IF SFTVMU PG Trivial' == Trivial' UIBU JT True

 8F DPVMEƊWF XSJUUFO UIF EFƶOJUJPO PG (==) VTJOH QSFƶY OP


UBUJPO JOTUFBE PG JOƶY CZ XSBQQJOH UIF PQFSBUPS JO QBSFO
UIFTFT /PUF UIJT JT KVTU CFJOH TIPXO BT BO BMUFSBUJWF ZPV
DBOƊU IBWF UXP UZQFDMBTT JOTUBODFT GPS UIF TBNF UZQF 8FƊMM
FYQMBJO NPSF BCPVU UIJT MBUFS CVU UZQFDMBTT JOTUBODFT BSF
VOJRVF UP B HJWFO UZQF :PV DBO USZ IBWJOH CPUI JO UIF
TBNF ƶMF CVU ZPVƊMM HFU BO FSSPS

0LBZ MFUƊT TUSFUDI PVS MFHT B CJU BOE USZ TPNFUIJOH B CJU
MFTTTrivial 8FƊMM NBLF PVS PXO EBUBUZQFT ƈ POF GPS UIF
EBZT PG UIF XFFL BOE POF GPS UIF EBUF UIBU NBLFT VTF PG UIF
DayOfWeek UZQF
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

data DayOfWeek =
Mon | Tue | Weds | Thu | Fri | Sat | Sun

-- day of week and numerical day of month


data Date =
Date DayOfWeek Int

4JODF UIFTF BSF OPU QSFCBLFE EBUBUZQFT JO )BTLFMM UIFZ IBWF


OP UZQFDMBTT JOTUBODFT BU BMM "T UIFZ TUBOE UIFSF JT OPUIJOH
ZPV DBO EP XJUI UIFN CFDBVTF OP PQFSBUJPOT BSF EFƶOFE GPS
UIFN -FUƊT ƶY UIBU 5IF ƶSTU Eq JOTUBODF XFƊMM XSJUF JT GPS
DayOfWeek BOE JT B CJU UFEJPVT UP XSJUF PVU CVU TIPVMEOƊU DPOUBJO
BOZ TVSQSJTFT

instance Eq DayOfWeek where


(==) Mon Mon = True
(==) Tue Tue = True
(==) Weds Weds = True
(==) Thu Thu = True
(==) Fri Fri = True
(==) Sat Sat = True
(==) Sun Sun = True
(==) _ _ = False

/PX XFƊMM XSJUF BO Eq JOTUBODF GPS PVS Date UZQF 5IJT POF JT
NPSF JOUFSFTUJOH
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

instance Eq Date where


(==) (Date weekday dayOfMonth)
(Date weekday' dayOfMonth') =
weekday == weekday' && dayOfMonth == dayOfMonth'

*O UIF Eq JOTUBODF GPS Date XF EJEOƊU SFDBQJUVMBUF IPX FRVBM


JUZ GPS DayOfWeek BOE Int WBMVFT XPSLFE XF TJNQMZ TBJE UIBU UIF
EBUFT XFSF FRVBM JG BMM PG UIFJS DPOTUJUVFOU WBMVFT XFSF FRVBM
/PUF BMTP UIBU UIF DPNQJMFS BMSFBEZ FYQFDUT UIF BSHVNFOUT
PG Date UP CF B DayOfWeek WBMVF BOE BO Int TP XF EP OPU OFFE
UP TQFDJGZ UIBU #BTFE PO XIBU JU LOPXT BCPVU UIPTF UISFF
UZQFT UIJT JT FOPVHI JOGPSNBUJPO GPS VT UP UFTU Date WBMVFT GPS
FRVBMJUZ
%PFT JU XPSL

Prelude> Date Thu 10 == Date Thu 10


True
Prelude> Date Thu 10 == Date Thu 11
False
Prelude> Date Thu 10 == Date Weds 10
False

*U DPNQJMFT BOE JU SFUVSOT XIBU XF XBOU BǒFS UISFF DVSTPSZ


DIFDLT ƈ TIJQ JU
8FƊMM QPJOU PVU POF PUIFS UIJOH BCPVU UIFTF UZQFT

*Main> Date Thu 10


$)"15&3  -&44 "%)0$ 10-:.031)*4. 

<interactive>:26:1:
No instance for (Show Date) arising from a use of ‘print’
In a stmt of an interactive GHCi command: print it

8F XSPUF BO Eq JOTUBODF TP XF DBO UFTU UIF WBMVFT GPS FRVBM


JUZ CVU XF DBOƊU QSJOU UIFN JO UIF 3&1- CFDBVTF XF QSPWJEFE
OP Show JOTUBODF *G ZPVƊE MJLF UP ƶY UIBU ZPV DBO TUJDL B deriving
Show DMBVTF PO UIF FOE PG FBDI PG UIF EBUBUZQFT BCPWF

1BSUJBM GVODUJPOT  OPU TP TUSBOHF EBOHFS

8FƊWF NFOUJPOFE QBSUJBM BQQMJDBUJPO PG GVODUJPOT QSFWJPVTMZ


CVU UIF UFSN QBSUJBM GVODUJPO SFGFST UP TPNFUIJOH EJƵFSFOU "
QBSUJBM GVODUJPO JT POF UIBU EPFTOƊU IBOEMF BMM UIF QPTTJCMF DBTFT
TP UIFSF BSF QPTTJCMF TDFOBSJPT JO XIJDI XF IBWFOƊU EFƶOFE
BOZ XBZ GPS UIF DPEF UP FWBMVBUF
8F OFFE UP UBLF DBSF UP BWPJE QBSUJBM GVODUJPOT JO HFOFSBM
JO )BTLFMM CVU UIJT NVTU CF FTQFDJBMMZ LFQU JO NJOE XIFO XF
IBWF B UZQF XJUI NVMUJQMF DBTFT TVDI BT DayOfWeek 8IBU JG XF
IBE NBEF B NJTUBLF JO UIF Eq JOTUBODF
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

data DayOfWeek =
Mon | Tue | Weds | Thu | Fri | Sat | Sun

instance Eq DayOfWeek where


(==) Mon Mon = True
(==) Tue Tue = True
(==) Weds Weds = True
(==) Thu Thu = True
(==) Fri Fri = True
(==) Sat Sat = True
(==) Sun Sun = True

8IBU JG UIF BSHVNFOUT BSF EJƵFSFOU 8F GPSHPU PVS VODPO


EJUJPOBM DBTF 5IJT XJMM BQQFBS UP CF ƶOF XIFOFWFS UIF BSHV
NFOUT BSF UIF TBNF CVU CMPX VQ JO PVS GBDFT XIFO UIFZƊSF
OPU

Prelude> Mon == Mon


True

Prelude> Mon == Tue


*** Exception: code/derivingInstances.hs:
(19,3)-(25,23):
Non-exhaustive patterns in function ==

8FMM UIBU TUJOLT 8F EFƶOJUFMZ EJEOƊU TUBSU MFBSOJOH )BTLFMM


CFDBVTF XF XBOUFE TUVƵ UP CMPX VQ BU SVOUJNF 4P XIBU HJWFT
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

5IF HPPE OFXT JT UIFSF JT TPNFUIJOH ZPV DBO EP UP HFU NPSF


IFMQ GSPN ()$ PO UIJT *G XF UVSO BMM XBSOJOHT PO XJUI UIF
Wall ƷBH JO PVS 3&1- PS JO PVS CVJME DPOƶHVSBUJPO ƈ NPSF PO
UIBU MBUFS
UIFO ()$ XJMM MFU VT LOPX XIFO XFƊSF OPU IBOEMJOH
BMM DBTFT

Prelude> :set -Wall


Prelude> :l code/derivingInstances.hs
[1 of 1] Compiling DerivingInstances

code/derivingInstances.hs:19:3: Warning:
Pattern match(es) are non-exhaustive
In an equation for ‘==’:
Patterns not matched:
Mon Tue
Mon Weds
Mon Thu
Mon Fri
...
Ok, modules loaded: DerivingInstances.

:PVƊMM ƶOE UIBU JG ZPV ƶY ZPVS JOTUBODF BOE QSPWJEF UIF


GBMMCBDL DBTF UIBU SFUVSOT False JUƊMM TUPQ TRVBXLJOH BCPVU UIF
OPOFYIBVTUJWF QBUUFSOT
1BSUJBM GVODUJPOT BSF OPU POMZ B DPODFSO XJUI UZQFDMBTT JO
TUBODFT UIPVHI 8F XJMM EJTDVTT UIJT NPSF JO UIF OFYU DIBQUFS
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

CVU JUƊT BMTP B DPODFSO XJUI BOZ GVODUJPO UIBU EPFTOƊU IBOEMF
BMM QPTTJCMF JOQVUT TVDI BT

-- this'll blow up for any input not ``1''

f :: Int -> Bool


f 1 = True

*G ZPV DPNQJMF PS MPBE UIJT ZPVƊMM HFU BOPUIFS XBSOJOH BT


TVNJOH ZPV TUJMM IBWF -Wall UVSOFE PO
 *O UIJT DBTF CFDBVTF
Int JT B IVHF UZQF XJUI NBOZ WBMVFT JUƊT VTJOH OPUBUJPO UIBU TBZT
ZPVƊSF OPU IBOEMJOH BMM JOQVUT UIBU BSFOƊU UIF OVNCFS 

Pattern match(es) are non-exhaustive


In an equation for ‘f’:
Patterns not matched:
GHC.Types.I# #x with #x `notElem` [1#]

*G ZPV BEE BOPUIFS DBTF TVDI UIBU ZPVƊSF IBOEMJOH POF NPSF
JOQVU JU XJMM BEE UIBU UP UIF TFU PG WBMVFT ZPV BSF IBOEMJOH

f :: Int -> Bool


f 1 = True
f 2 = True

Pattern match(es) are non-exhaustive


In an equation for ‘f’:
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

Patterns not matched:


GHC.Types.I# #x with #x `notElem` [1#, 2#]

f :: Int -> Bool


f 1 = True
f 2 = True
f 3 = True

Pattern match(es) are non-exhaustive


In an equation for ‘f’:
Patterns not matched:
GHC.Types.I# #x with #x `notElem` [1#, 2#, 3#]

4P PO BOE TP GPSUI 5IF SFBM BOTXFS IFSF JT UP IBWF BO


VODPOEJUJPOBM DBTF UIBU NBUDIFT FWFSZUIJOH

-- This will compile without complaint


-- and is not partial.

f :: Int -> Bool


f 1 = True
f 2 = True
f 3 = True
f _ = False

"OPUIFS TPMVUJPO JT UP VTF B EBUBUZQF UIBU JTOƊU IVHF MJLF Int


JG ZPV POMZ IBWF B GFX DBTFT ZPV XBOU UP DPOTJEFS
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

-- Seriously. It's huge.

Prelude> minBound :: Int


-9223372036854775808
Prelude> maxBound :: Int
9223372036854775807

*G ZPV XBOU ZPVS EBUB UP EFTDSJCF POMZ B IBOEGVM PG DBTFT


XSJUF UIFN EPXO JO B TVN UZQF MJLF UIF DayOfWeek EBUBUZQF XF
TIPXFE ZPV FBSMJFS %POƊU VTF Int BT BO JNQMJDJU TVN UZQF BT $
QSPHSBNNFST DPNNPOMZ EP

4PNFUJNFT XF OFFE UP BTL GPS NPSF

8IFO XFƊSF XSJUJOH BO JOTUBODF PG B UZQFDMBTT TVDI BT Eq GPS


TPNFUIJOH XJUI QPMZNPSQIJD QBSBNFUFST TVDI BT Identity
CFMPX XFƊMM TPNFUJNFT OFFE UP SFRVJSF PVS BSHVNFOU PS BSHV
NFOUT UP QSPWJEF TPNF UZQFDMBTT JOTUBODFT GPS VT JO PSEFS UP
XSJUF BO JOTUBODF GPS UIF EBUBUZQF DPOUBJOJOH UIFN

data Identity a =
Identity a

instance Eq (Identity a) where


(==) (Identity v) (Identity v') = v == v'

8IBU XF XBOU UP EP IFSF JT SFMZ PO XIBUFWFS Eq JOTUBODFT UIF


BSHVNFOU UP Identity XSJUUFO BT Ԑ JO UIF EBUBUZQF EFDMBSBUJPO
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

BOE ԥ JO UIF JOTUBODF EFƶOJUJPO


IBT BMSFBEZ 5IFSF JT POF
QSPCMFN XJUI UIJT BT JU TUBOET UIPVHI

No instance for (Eq a) arising from a use of ‘==’


Possible fix: add (Eq a) to the
context of the instance declaration

In the expression: v == v'


In an equation for ‘==’:
(==) (Identity v) (Identity v') = v == v'
In the instance declaration for ‘Eq (Identity a)’

5IF QSPCMFN IFSF JT UIBU ԥ BOE ԥ஥ BSF CPUI PG UZQF Ԑ CVU


XF EPOƊU SFBMMZ LOPX BOZUIJOH BCPVU Ԑ *O UIJT DBTF XF DBOƊU
BTTVNF JU IBT BO Eq JOTUBODF )PXFWFS XF DBO VTF UIF TBNF
UZQFDMBTT DPOTUSBJOU TZOUBY XF TBX XJUI GVODUJPOT JO PVS JO
TUBODF EFDMBSBUJPO

instance Eq a => Eq (Identity a) where


(==) (Identity v) (Identity v') = v == v'

/PX JUƊMM XPSL CFDBVTF XF LOPX Ԑ IBT UP IBWF BO JOTUBODF PG


Eq "EEJUJPOBMMZ )BTLFMM XJMM FOTVSF XF EPOƊU BUUFNQU UP DIFDL
FRVBMJUZ XJUI WBMVFT UIBU EPOƊU IBWF BO Eq JOTUBODF BU DPNQJMF
UJNF

Prelude> Identity NoEqInst == Identity NoEqInst


$)"15&3  -&44 "%)0$ 10-:.031)*4. 

No instance for (Eq NoEqInst)


arising from a use of ‘==’

In the expression:
Identity NoEqInst == Identity NoEqInst

In an equation for ‘it’:


it = Identity NoEqInst == Identity NoEqInst

8F DPVME BTL GPS NPSF UIBO XF OFFE JO PSEFS UP PCUBJO BO


BOTXFS TVDI BT CFMPX XIFSF XF BTL GPS BO Ord JOTUBODF GPS Ԑ
CVU UIFSFƊT OP SFBTPO UP EP TP TJODF Eq SFRVJSFT MFTT UIBO Ord
BOE EPFT FOPVHI GPS XIBU XF OFFE IFSF

instance Ord a => Eq (Identity a) where


(==) (Identity v) (Identity v') =
compare v v' == EQ

5IBU XJMM DPNQJMF CVU JUƊT OPU DMFBS XIZ ZPVƊE EP JU .BZCF
ZPV IBWF ZPVS PXO TFDSFU SFBTPOT

&YFSDJTFT &R *OTUBODFT

8SJUF UIF Eq JOTUBODF GPS UIF EBUBUZQF QSPWJEFE

 *UƊT OPU B UZQP XFƊSF KVTU CFJOH DVUF XJUI UIF OBNF
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

data TisAnInteger =
TisAn Integer

 data TwoIntegers =
Two Integer Integer

 data StringOrInt =
TisAnInt Int
| TisAString String

 data Pair a =
Pair a a

 data Tuple a b =
Tuple a b

 data Which a =
ThisOne a
| ThatOne a

 data EitherOr a b =
Hello a
| Goodbye b

 /VN
8F IBWF TFFO B MPU PG Num BU UIJT QPJOU TP XFƊMM USZ OPU UP HP
PO UPP MPOH BCPVU JU *U JT B UZQFDMBTT JNQMFNFOUFE CZ NPTU
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

OVNFSJD UZQFT "T XF EJE XJUI Eq XF XJMM RVFSZ UIF JOGPSNBUJPO


BOE FYBNJOF JUT TFU PG QSFEFƶOFE GVODUJPOT

class Num a where


(+) :: a -> a -> a
(*) :: a -> a -> a
(-) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a

"OE JUT MJTU PG JOTUBODFT OPU RVJUF DPNQMFUF




instance Num Integer


instance Num Int
instance Num Float
instance Num Double

8FƊWF TFFO NPTU PG UIJT JOGPSNBUJPO CFGPSF JO POF GPSN


PS BOPUIFS DPNNPO BSJUINFUJD GVODUJPOT XJUI UIFJS UZQF
TJHOBUVSFT BU UIF UPQ fromInteger JT TJNJMBS UP fromIntegral CVU
SFTUSJDUFE UP Integer SBUIFS UIBO BMM JOUFHSBM OVNCFST
QMVT B MJTU
PG UZQFT UIBU JNQMFNFOU UIJT UZQFDMBTT OVNFSJD UZQFT XFƊWF
MPPLFE BU QSFWJPVTMZ /P TVSQSJTFT IFSF
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

*OUFHSBM
5IF UZQFDMBTT DBMMFE Integral IBT UIF GPMMPXJOH EFƶOJUJPO

class (Real a, Enum a) => Integral a where


quot :: a -> a -> a
rem :: a -> a -> a
div :: a -> a -> a
mod :: a -> a -> a
quotRem :: a -> a -> (a, a)
divMod :: a -> a -> (a, a)
toInteger :: a -> Integer

5IF UZQFDMBTT DPOTUSBJOU (Real a, Enum a) => NFBOT UIBU BOZ


UZQF UIBU JNQMFNFOUT Integral NVTU BMSFBEZ IBWF JOTUBODFT GPS
Real BOE Enum UZQFDMBTTFT *O B WFSZ SFBM TFOTF UIF UVQMF TZOUBY
IFSF EFOPUFT UIF DPOKVODUJPO PG UZQFDMBTT DPOTUSBJOUT PO ZPVS
UZQF WBSJBCMFT "O JOUFHSBM UZQF NVTU CF CPUI B SFBM OVNCFS
BOE FOVNFSBCMF NPSF PO Enum MBUFS
BOE UIFSFGPSF NBZ FN
QMPZ UIF NFUIPET FBDI PG UIPTF UZQFDMBTTFT *O UVSO UIF Real
UZQFDMBTT JUTFMG SFRVJSFT BO JOTUBODF PG Num 4P UIF Integral
UZQFDMBTT NBZ QVU UIF NFUIPET PG Real BOE Num JOUP FƵFDU JO
BEEJUJPO UP UIPTF PG Enum
 4JODF Real DBOOPU PWFSSJEF UIF NFUI
PET PG Num UIJT UZQFDMBTT JOIFSJUBODF JT POMZ BEEJUJWF BOE UIF
BNCJHVJUZ QSPCMFNT DBVTFE CZ NVMUJQMF JOIFSJUBODF JO TPNF
QSPHSBNNJOH MBOHVBHFT ƈ UIF TPDBMMFE ƌEFBEMZ EJBNPOE PG
EFBUIƍ ƈ BSF BWPJEFE
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

&YFSDJTFT 5VQMF &YQFSJNFOU -PPL BU UIF UZQFT HJWFO GPS


quotRem BOE divMod 8IBU EP ZPV UIJOL UIPTF GVODUJPOT EP 5FTU
ZPVS IZQPUIFTFT CZ QMBZJOH XJUI UIFN JO UIF 3&1- 8FƊWF
HJWFO ZPV B TBNQMF UP TUBSU XJUI CFMPX

Prelude> let ones x = snd (divMod x 10)

'SBDUJPOBM
Num JT B TVQFSDMBTT PG Fractional 5IF Fractional UZQFDMBTT JT
EFƶOFE BT GPMMPXT

class (Num a) => Fractional a where


(/) :: a -> a -> a
recip :: a -> a
fromRational :: Rational -> a

5IJT UZQFDMBTT EFDMBSBUJPO DSFBUFT B DMBTT OBNFE Fractional


XIJDI SFRVJSFT JUT UZQF BSHVNFOU Ԑ UP IBWF BO JOTUBODF PG Num
JO PSEFS UP DSFBUF BO JOTUBODF PG Fractional 5IJT JT BOPUIFS
FYBNQMF PG UZQFDMBTT JOIFSJUBODF Fractional BQQMJFT UP GFXFS
OVNCFST UIBO Num EPFT BOE JOTUBODFT PG UIF Fractional DMBTT
DBO VTF UIF GVODUJPOT EFƶOFE JO Num CVU OPU BMM Num DBO VTF
UIF GVODUJPOT EFƶOFE JO Fractional CFDBVTF OPUIJOH JO NumƊT
EFƶOJUJPO SFRVJSFT BO JOTUBODF PG Fractional 5IFSF JT B DIBSU
BU UIF FOE PG UIF DIBQUFS UP IFMQ ZPV WJTVBMJ[F UIJT JOGPSNBUJPO
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

8F DBO TFF UIJT XJUI PSEJOBSZ GVODUJPOT


'JSTU MFU VT DPOTJEFS UIJT GVODUJPO JOUFOUJPOBMMZ XJUIPVU B
UZQF QSPWJEFE

divideThenAdd x y = (x / y) + 1

8FƊMM MPBE UIJT XJUI B UZQF UIBU BTLT POMZ GPS B Num JOTUBODF

divideThenAdd :: Num a => a -> a -> a


divideThenAdd x y = (x / y) + 1

"OE ZPVƊMM HFU UIF UZQF FSSPS

Could not deduce (Fractional a)


arising from a use of ‘/’
from the context (Num a)
bound by the type signature for
divideThenAdd :: Num a => a -> a -> a

/PX JG XF POMZ DBSFE BCPVU IBWJOH UIF Num DPOTUSBJOU XF


DPVME NPEJGZ PVS GVODUJPO UP OPU VTF (/) XIJDI SFRVJSFT Fractional

-- This works fine.


-- (+) and (-) are both provided by Num

subtractThenAdd :: Num a => a -> a -> a


subtractThenAdd x y = (x - y) + 1
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

0S XF DBO DIBOHF UIF UZQF SBUIFS UIBO NPEJGZJOH UIF GVOD


UJPO JUTFMG

-- This works fine.

divideThenAdd :: Fractional a => a -> a -> a


divideThenAdd x y = (x / y) + 1

1VU PO ZPVS UIJOLJOH DBQ 8IZ EJEOƊU XF OFFE UP NBLF UIF


UZQF PG UIF GVODUJPO XF XSPUF SFRVJSF CPUI UZQFDMBTTFT 8IZ
EJEOƊU XF IBWF UP EP UIJT

f :: (Num a, Fractional a) => a -> a -> a

$POTJEFS XIBU JU NFBOT GPS TPNFUIJOH UP CF B TVCTFU PG B


MBSHFS TFU PG PCKFDUT

 5ZQFEFGBVMUJOH UZQFDMBTTFT


8IFO ZPV IBWF B UZQFDMBTTDPOTUSBJOFE BE IPD
QPMZNPSQIJD
WBMVF BOE OFFE UP FWBMVBUF JU UIF QPMZNPSQIJTN NVTU CF SF
TPMWFE UP B TQFDJƶD DPODSFUF UZQF 5IF DPODSFUF UZQF NVTU
IBWF BO JOTUBODF GPS BMM UIF SFRVJSFE UZQFDMBTT JOTUBODFT UIBU
JT JG JU JT SFRVJSFE UP JNQMFNFOU Num BOE Fractional UIFO UIF
DPODSFUF UZQF DBOƊU CF BO Int
 0SEJOBSJMZ UIF DPODSFUF UZQF
XPVME DPNF GSPN UIF UZQF TJHOBUVSF ZPVƊWF TQFDJƶFE PS GSPN
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

UZQF JOGFSFODF TVDI BT XIFO B Num a => a JT VTFE JO BO FYQSFT


TJPO UIBU FYQFDUT BO Integer XIJDI GPSDFT UIF QPMZNPSQIJD
OVNCFS WBMVF UP DPODSFUJ[F BT BO Integer #VU JO TPNF DBTFT
QBSUJDVMBSMZ XIFO ZPVƊSF XPSLJOH JO UIF ()$J 3&1- ZPV XJMM
OPU IBWF TQFDJƶFE B DPODSFUF UZQF GPS B QPMZNPSQIJD WBMVF *O
UIPTF TJUVBUJPOT UIF UZQFDMBTT XJMM EFGBVMU UP B DPODSFUF UZQF
BOE UIF EFGBVMU UZQFT BSF BMSFBEZ TFU JO UIF MJCSBSJFT
8IFO XF EP UIJT JO UIF 3&1-

Prelude> 1 / 2
0.5

0VS SFTVMU 0.5 BQQFBST UIF XBZ JU EPFT CFDBVTF JU EFGBVMUT UP


Double 6TJOH UIF UZQF BTTJHONFOU PQFSBUPS :: XF DBO BTTJHO B
NPSF TQFDJƶD UZQF BOE DJSDVNWFOU UIF EFGBVMU UP Double

Prelude> 1 / 2 :: Float
0.5
Prelude> 1 / 2 :: Double
0.5
Prelude> 1 / 2 :: Rational
1 % 2

5IF )BTLFMM 3FQPSU TQFDJƶFT UIF GPMMPXJOH EFGBVMUT SFMFWBOU


UP OVNFSJDBM DPNQVUBUJPOT

5IF )BTLFMM 3FQPSU JT UIF TUBOEBSE UIBU TQFDJƶFT UIF MBOHVBHF BOE TUBOEBSE MJCSBSJFT
GPS )BTLFMM 5IF NPTU SFDFOU WFSTJPO JT )BTLFMM 3FQPSU  XIJDI DBO CF GPVOE BU
https://www.haskell.org/onlinereport/haskell2010/
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

default Num Integer


default Real Integer
default Enum Integer
default Integral Integer
default Fractional Double
default RealFrac Double
default Floating Double
default RealFloat Double

Num Real FUD BSF UZQFDMBTTFT BOE Integer BOE Double BSF
UIF UZQFT UIFZ EFGBVMU UP 5IJT UZQF EFGBVMUJOH GPS Fractional
NFBOT UIBU

(/) :: Fractional a => a -> a -> a

DIBOHFT UP

(/) :: Double -> Double -> Double

JG ZPV EPOƊU TQFDJGZ UIF DPODSFUF UZQF EFTJSFE GPS (/) "
TJNJMBS FYBNQMF CVU GPS Integral XPVME CF

div :: Integral a => a -> a -> a

EFGBVMUJOH UP

div :: Integer -> Integer -> Integer


$)"15&3  -&44 "%)0$ 10-:.031)*4. 

5IF UZQFDMBTT DPOTUSBJOU JT TVQFSƷVPVT XIFO UIF UZQFT BSF


DPODSFUF 0O UIF PUIFS IBOE ZPV NVTU TQFDJGZ XIJDI UZQF
DMBTTFT ZPV XBOU UZQF WBSJBCMFT UP IBWF JNQMFNFOUFE 5IF VTF
PG QPMZNPSQIJD WBMVFT XJUIPVU UIF BCJMJUZ UP JOGFS B TQFDJƶD
UZQF BOE OP EFGBVMU SVMF XJMM DBVTF ()$ UP DPNQMBJO BCPVU BO
BNCJHVPVT UZQF
5IF GPMMPXJOH XJMM XPSL CFDBVTF BMM UIF UZQFT CFMPX JNQMF
NFOU UIF Num UZQFDMBTT

Prelude> let x = 5 + 5 :: Int


Prelude> x
10

Prelude> let x = 5 + 5 :: Integer


Prelude> x
10

Prelude> let x = 5 + 5 :: Float


Prelude> x
10.0

Prelude> let x = 5 + 5 :: Double


Prelude> x
10.0

/PX XF DBO NBLF UIJT UZQF NPSF TQFDJƶD BOE UIF QSPDFTT
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

XJMM CF TJNJMBS *O UIJT DBTF MFUƊT VTF Integer XIJDI JNQMFNFOUT


Num

let x = 10 :: Integer

let y = 5 :: Integer

-- These are the declared types for these


-- functions, because they're from Num.
(+) :: Num a => a -> a -> a
(*) :: Num a => a -> a -> a
(-) :: Num a => a -> a -> a

/PX BOZ GVODUJPOT GSPN Num BSF HPJOH UP BVUPNBUJDBMMZ HFU


TQFDJBMJ[FE UP Integer XIFO XF BQQMZ UIFN UP UIF ԧ PS Ԩ WBMVFT

Prelude> :t (x+)
(x+) :: Integer -> Integer

-- For
(+) :: Num a => a -> a -> a
-- When 'a' is Integer
(+) :: Integer -> Integer -> Integer
-- Apply the first argument
(x+) :: Integer -> Integer
-- Applying the second and last argument
(x+y) :: Integer
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

-- Final result was Integer.

8F DBO EFDMBSF NPSF TQFDJƶD NPOPNPSQIJD


GVODUJPOT
GSPN NPSF HFOFSBM QPMZNPSQIJD
GVODUJPOT

let add = (+) :: Integer -> Integer -> Integer

8F DBOOPU HP JO UIF PUIFS EJSFDUJPO CFDBVTF XF MPTU UIF


HFOFSBMJUZ PG Num XIFO XF TQFDJBMJ[FE UP Integer

Prelude> :t id
id :: a -> a
Prelude> let numId = id :: Num a => a -> a
Prelude> let intId = numId :: Integer -> Integer
Prelude> let altNumId = intId :: Num a => a -> a

Could not deduce (a1 ~ Integer)


from the context (Num a)
bound by the inferred type of
altNumId :: Num a => a -> a

or from (Num a1)


bound by an expression type signature:
Num a1 => a1 -> a1

‘a1’ is a rigid type variable bound by


an expression type signature:
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

Num a1 => a1 -> a1

Expected type: a1 -> a1


Actual type: Integer -> Integer
In the expression: intId :: Num a => a -> a

In an equation for ‘altNumId’:


altNumId = intId :: Num a => a -> a

5IF FYQFDUFE UZQF BOE UIF BDUVBM UZQF EPOƊU NBUDI 3FNFNCFS
UIF BDUVBM UZQF JT UIF UZQF XF QSPWJEFE UIF FYQFDUFE UZQF
JT XIBU UIF DPNQJMFS FYQFDUT )FSF UIF BDUVBM UZQF JT NPSF
DPODSFUF UIBO UIF FYQFDUFE UZQF 5ZQFT DBO CF NBEF NPSF
TQFDJƶD CVU OPU NPSF HFOFSBM PS QPMZNPSQIJD

 0SE
/FYU XFƊMM UBLF B MPPL BU B UZQFDMBTT DBMMFE Ord 8FƊWF QSFWJPVTMZ
OPUFE UIBU UIJT UZQFDMBTT DPWFST UIF UZQFT PG UIJOHT UIBU DBO CF
QVU JO PSEFS *G ZPV VTF :info GPS Ord JO ZPVS 3&1- ZPV XJMM
ƶOE B WFSZ MBSHF OVNCFS PG JOTUBODFT GPS UIJT UZQFDMBTT 8FƊSF
HPJOH UP QBSF JU EPXO B CJU BOE GPDVT PO UIF FTTFOUJBMT CVU BT
BMXBZT XF FODPVSBHF ZPV UP FYQMPSF UIJT GVSUIFS PO ZPVS PXO

Prelude> :info Ord


$)"15&3  -&44 "%)0$ 10-:.031)*4. 

class Eq a => Ord a where


compare :: a -> a -> Ordering
(<) :: a -> a -> Bool
(>=) :: a -> a -> Bool
(>) :: a -> a -> Bool
(<=) :: a -> a -> Bool
max :: a -> a -> a
min :: a -> a -> a

instance Ord a => Ord (Maybe a)


instance (Ord a, Ord b) => Ord (Either a b)
instance Ord Integer
instance Ord a => Ord [a]
instance Ord Ordering
instance Ord Int
instance Ord Float
instance Ord Double
instance Ord Char
instance Ord Bool

/PUBCMZ BU UIF UPQ XF IBWF BOPUIFS UZQFDMBTT DPOTUSBJOU


Ord JT DPOTUSBJOFE CZ Eq CFDBVTF JG ZPVƊSF HPJOH UP DPNQBSF
JUFNT JO B MJTU BOE QVU UIFN JO PSEFS ZPV OFFE B XBZ UP EF
UFSNJOF JG UIFZ BSF FRVBM 4P Ord SFRVJSFT Eq BOE JUT NFUIPET
5IF GVODUJPOT UIBU DPNF TUBOEBSE JO UIJT DMBTT IBWF UP EP XJUI
PSEFSJOH 4PNF PG UIFN XJMM HJWF ZPV B SFTVMU PG Bool BOE
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

XFƊWF QMBZFE B CJU XJUI UIPTF GVODUJPOT -FUƊT TFF XIBU B GFX
PUIFST EP

Prelude> compare 7 8
LT
Prelude> compare 4 (-4)
GT
Prelude> compare 4 4
EQ
Prelude> compare "Julie" "Chris"
GT
Prelude> compare True False
GT
Prelude> compare True True
EQ

5IF compare GVODUJPO XPSLT GPS BOZ PG UIF UZQFT MJTUFE BCPWF
UIBU JNQMFNFOU UIF Ord UZQFDMBTT JODMVEJOH Bool CVU VOMJLF
UIF <, >, >=, and <= PQFSBUPST UIJT SFUVSOT BO Ordering WBMVF
JOTUFBE PG B Bool WBMVF
:PV NBZ OPUJDF UIBU True JT HSFBUFS UIBO False 1SPYJNBMMZ
UIJT JT EVF UP IPX UIF Bool EBUBUZQF JT EFƶOFE False | True
5IFSF NBZ CF B NPSF JOUFSFTUJOH VOEFSMZJOH SFBTPO JG ZPV
QSFGFS UP QPOEFS UIF QIJMPTPQIJDBM JNQMJDBUJPOT
5IF max BOE min GVODUJPOT XPSL JO B TJNJMBSMZ TUSBJHIUGPS
XBSE GBTIJPO GPS BOZ UZQF UIBU JNQMFNFOUT UIJT UZQFDMBTT
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

Prelude> max 7 8
8
Prelude> min 10 (-10)
-10
Prelude> max (3, 4) (2, 3)
(3,4)
Prelude> min [2, 3, 4, 5] [3, 4, 5, 6]
[2,3,4,5]
Prelude> max "Julie" "Chris"
"Julie"

#Z MPPLJOH BU UIF UZQF TJHOBUVSF XF DBO TFF UIBU UIFTF GVOD


UJPOT IBWF UXP QBSBNFUFST *G ZPV XBOU UP VTF UIFTF UP EFUFS
NJOF UIF NBYJNVN PS NJOJNVN PG UISFF WBMVFT ZPV DBO OFTU
UIFN

Prelude> max 7 (max 8 9)


9

*G ZPV USZ UP HJWF JU UPP GFX BSHVNFOUT ZPV XJMM HFU UIJT
TUSBOHFTFFFNJOH NFTTBHF

Prelude> max "Julie"

No instance for (Show ([Char] -> [Char]))


-- [1] [2] [ 3 ]
arising from a use of ‘print’
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

-- [4]
In a stmt of an interactive GHCi command: print it
-- [ 5 ]

 )BTLFMM DPVMEOƊU ƶOE BO JOTUBODF PG B UZQFDMBTT GPS B WBMVF


PG B HJWFO UZQF

 5IF UZQFDMBTT JU DPVMEOƊU ƶOE BO JOTUBODF GPS XBT Show UIF


UZQFDMBTT UIBU BMMPXT ()$J UP QSJOU WBMVFT JO ZPVS UFSNJOBM
.PSF PO UIJT JO UIF GPMMPXJOH TFDUJPOT

 *U DPVMEOƊU ƶOE BO JOTUBODF PG Show GPS UIF UZQF String ->


String /PUIJOH XJUI UZQF (->) TIPVME IBWF B Show JOTUBODF
BT B HFOFSBM SVMF CFDBVTF (->) EFOPUFT B GVODUJPO SBUIFS
UIBO B DPOTUBOU WBMVF

 8F XBOUFE BO JOTUBODF PG Show CFDBVTF XF JOEJSFDUMZ

JOWPLFE print XIJDI IBT UZQF print :: Show a => a -> IO


() ƈ OPUF UIF DPOTUSBJOU GPS Show

 5IF JOUFSBDUJWF ()$J DPNNBOE print it JOWPLFE print


PO PVS CFIBMG

"OZ UJNF XF BTL ()$J UP QSJOU B SFUVSO WBMVF JO PVS UFS


NJOBM XF BSF JOEJSFDUMZ JOWPLJOH print XIJDI IBT UIF UZQF
Show a => a -> IO () 5IF ƶSTU BSHVNFOU UP print NVTU IBWF BO
JOTUBODF PG Show 5IF FSSPS NFTTBHF JT CFDBVTF max BQQMJFE UP
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

B TJOHMF String BSHVNFOU OFFET BOPUIFS BSHVNFOU CFGPSF JUƊMM


SFUVSO B String BLB [Char]
WBMVF UIBU JT ShowBCMF PS QSJOUBCMF
6OUJM XF BQQMZ JU UP B TFDPOE BSHVNFOU JUƊT TUJMM B GVODUJPO
BOE B GVODUJPO IBT OP JOTUBODF PG Show 5IF SFRVFTU UP print
B GVODUJPO SBUIFS UIBO B DPOTUBOU WBMVF SFTVMUT JO UIJT FSSPS
NFTTBHF

0SE JOTUBODFT
8FƊMM TFF NPSF FYBNQMFT PG XSJUJOH JOTUBODFT BT XF QSPDFFE
JO UIF CPPL BOE FYQMBJO NPSF UIPSPVHIMZ IPX UP XSJUF ZPVS
PXO EBUBUZQFT 8F XSPUF TPNF Eq JOTUBODFT FBSMJFS /PX XFƊMM
QSBDUJDF PVS JOTUBODFXSJUJOH TLJMMT UIJT JT POF PG UIF NPTU
OFDFTTBSZ TLJMMT JO )BTLFMM
CZ XSJUJOH Ord JOTUBODFT
8IFO ZPV EFSJWF Ord JOTUBODFT GPS B EBUBUZQF UIFZ SFMZ PO
UIF XBZ UIF EBUBUZQF JT EFƶOFE CVU JG ZPV XSJUF ZPVS PXO
JOTUBODF ZPV DBO EFƶOF UIF CFIBWJPS ZPV XBOU 8FƊMM VTF UIF
EBZT PG UIF XFFL BHBJO UP EFNPOTUSBUF

data DayOfWeek =
Mon | Tue | Weds | Thu | Fri | Sat | Sun
deriving (Ord, Show)

8F POMZ EFSJWFE Ord BOE Show UIFSF CFDBVTF ZPV TIPVME TUJMM
IBWF UIF Eq JOTUBODF XF XSPUF GPS UIJT EBUBUZQF JO TDPQF *G ZPV
EPOƊU ZPV IBWF UXP PQUJPOT CSJOH JU CBDL JOUP TDPQF CZ QVUUJOH
JU JOUP UIF ƶMF ZPVƊSF DVSSFOUMZ VTJOH PS EFSJWF BO Eq JOTUBODF
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

GPS UIF EBUBUZQF OPX CZ BEEJOH JU JOTJEF UIF QBSFOUIFTFT :PV


DBOƊU IBWF BO Ord JOTUBODF VOMFTT ZPV BMTP IBWF BO Eq JOTUBODF
TP UIF DPNQJMFS XJMM DPNQMBJO JG ZPV EPOƊU EP POF OPU CPUI

PG UIPTF UXP UIJOHT


7BMVFT UP UIF MFǒ BSF ƌMFTT UIBOƍ WBMVFT UP UIF SJHIU BT JG UIFZ
XFSF QMBDFE PO B OVNCFS MJOF

*Main> Mon > Tue


False
*Main> Sun > Mon
True
*Main> compare Tue Weds
LT

#VU JG XF XBOUFE UP FYQSFTT UIBU 'SJEBZ JT BMXBZT UIF CFTU


EBZ XF DBO XSJUF PVS PXO Ord JOTUBODF UP FYQSFTT UIBU

data DayOfWeek =
Mon | Tue | Weds | Thu | Fri | Sat | Sun
deriving (Eq, Show)

instance Ord DayOfWeek where


compare Fri Fri = EQ
compare Fri _ = GT
compare _ Fri = LT
compare _ _ = EQ
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

/PX JG XF DPNQBSF 'SJEBZ UP BOZ PUIFS EBZ 'SJEBZ JT BMXBZT


HSFBUFS "MM PUIFS EBZT ZPV OPUJDF BSF FRVBM JO WBMVF

*Main> compare Fri Sat


GT
*Main> compare Sat Mon
EQ
*Main> compare Fri Mon
GT
*Main> compare Sat Fri
LT
*Main> Mon > Fri
False
*Main> Fri > Sat
True

#VU XF EJE EFSJWF BO Eq JOTUBODF BCPWF TP XF EP HFU UIF


FYQFDUFE FRVBMJUZ CFIBWJPS

*Main> Sat == Mon


False
*Main> Fri == Fri
True

" GFX UIJOHT UP LFFQ JO NJOE BCPVU XSJUJOH Ord JOTUBODFT


'JSTU JU JT XJTF UP FOTVSF UIBU ZPVS Ord JOTUBODFT BHSFF XJUI ZPVS
Eq JOTUBODFT XIFUIFS UIF Eq JOTUBODFT BSF EFSJWFE PS NBOVBMMZ
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

XSJUUFO *G x == y UIFO compare x y TIPVME SFUVSO EQ "MTP ZPV


XBOU ZPVS Ord JOTUBODFT UP EFƶOF B TFOTJCMF UPUBM PSEFS :PV
FOTVSF UIJT JO QBSU CZ DPWFSJOH BMM DBTFT BOE OPU XSJUJOH QBSUJBM
JOTUBODFT BT XF OPUFE BCPWF XJUI Eq *O HFOFSBM ZPVS Ord
JOTUBODF TIPVME CF XSJUUFO TVDI UIBU XIFO compare x y SFUVSOT
LT UIFO compare y x SFUVSOT GT
8FƊMM MPPL JOUP XSJUJOH PVS PXO UZQFDMBTTFT BOE UZQFDMBTT
JOTUBODFT NPSF MBUFS JO UIF CPPL

0SE JNQMJFT &R


5IF GPMMPXJOH JTOƊU HPJOH UP UZQFDIFDL GPS SFBTPOT XF BMSFBEZ
DPWFSFE

check' :: a -> a -> Bool


check' a a' = a == a'

5IF FSSPS XF HFU NFOUJPOT UIBU XF OFFE Eq XIJDI NBLFT


TFOTF

No instance for (Eq a) arising from a use of ‘==’


Possible fix:
add (Eq a) to the context of
the type signature for check' :: a -> a -> Bool
In the expression: a == a'
In an equation for ‘check'’: check' a a' = a == a'

#VU XIBU JG XF BEE Ord JOTUFBE PG Eq BT JU BTLT


$)"15&3  -&44 "%)0$ 10-:.031)*4. 

check' :: Ord a => a -> a -> Bool


check' a a' = a == a'

*U TIPVME DPNQJMF KVTU ƶOF /PX Ord JTOƊU XIBU ()$ BTLFE
GPS TP XIZ EJE JU XPSL *U XPSLFE CFDBVTF BOZUIJOH UIBU QSP
WJEFT BO JOTUBODF PG Ord NVTU CZ EFƶOJUJPO BMTP BMSFBEZ IBWF BO
JOTUBODF PG Eq )PX EP XF LOPX "T XF TBJE BCPWF MPHJDBMMZ JU
NBLFT TFOTF UIBU ZPV DBOƊU PSEFS UIJOHT XJUIPVU UIF BCJMJUZ UP
DIFDL GPS FRVBMJUZ CVU XF DBO BMTP DIFDL :info Ord JO ()$J

Prelude> :info Ord


class Eq a => Ord a where

... buncha noise we don't care about...

5IF DMBTT EFƶOJUJPO PG Ord TBZT UIBU BOZ Ԑ XIJDI XBOUT UP


EFƶOF BO Ord JOTUBODF NVTU BMSFBEZ QSPWJEF BO Eq JOTUBODF 8F
DBO TBZ UIBU Eq JT B TVQFSDMBTT PG Ord
6TVBMMZ ZPV XBOU UIF NJOJNBMMZ TVƸDJFOU TFU PG DPOTUSBJOUT
PO BMM ZPVS GVODUJPOT ƈ TP XF XPVME VTF Eq JOTUFBE PG Ord JG UIF
BCPWF FYBNQMF XBT ƌSFBMƍ DPEF ƈ CVU XF EJE UIJT TP ZPV DPVME
HFU BO JEFB PG IPX DPOTUSBJOUT BOE TVQFSDMBTTJOH JO )BTLFMM
XPSL

&YFSDJTFT 8JMM 5IFZ 8PSL


/FYU UBLF B MPPL BU UIF GPMMPXJOH DPEF FYBNQMFT BOE USZ UP
EFDJEF JG UIFZ XJMM XPSL XIBU SFTVMU UIFZ XJMM SFUVSO JG UIFZ EP
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

BOE XIZ PS XIZ OPU CF TVSF BT BMXBZT UP UFTU UIFN JO ZPVS


3&1- PODF ZPV IBWF EFDJEFE PO ZPVS BOTXFS


 max (length [1, 2, 3]) (length [8, 9, 10, 11, 12])

 compare (3 * 4) (3 * 5)

 compare "Julie" True

 (5 + 3) > (3 + 6)

 &OVN
" UZQFDMBTT LOPXO BT Enum UIBU XF IBWF NFOUJPOFE QSFWJPVTMZ
TFFNT TJNJMBS UP Ord CVU JT TMJHIUMZ EJƵFSFOU 5IJT UZQFDMBTT
DPWFST UZQFT UIBU BSF FOVNFSBCMF UIFSFGPSF IBWF LOPXO QSF
EFDFTTPST BOE TVDDFTTPST 8F TIBMM USZ OPU UP CFMBCPS UIF QPJOU
CFDBVTF ZPV BSF QSPCBCMZ EFWFMPQJOH B HPPE JEFB PG IPX UP
RVFSZ BOE NBLF VTF PG UZQFDMBTT JOGPSNBUJPO

Prelude> :info Enum


class Enum a where
succ :: a -> a
pred :: a -> a
toEnum :: Int -> a
fromEnum :: a -> Int
enumFrom :: a -> [a]
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

enumFromThen :: a -> a -> [a]


enumFromTo :: a -> a -> [a]
enumFromThenTo :: a -> a -> a -> [a]

instance Enum Ordering


instance Enum Integer
instance Enum Int
instance Enum Char
instance Enum Bool
instance Enum ()
instance Enum Float
instance Enum Double

/VNCFST BOE DIBSBDUFST BSF LOPXO UP IBWF QSFEJDUBCMF


TVDDFTTPST BOE QSFEFDFTTPST TP UIFTF BSF QBSBEJHNBUJD DBTFT
PG FOVNFSBCJMJUZ

Prelude> succ 4
5
Prelude> pred 'd'
'c'
Prelude> succ 4.5
5.5

:PV DBO BMTP TFF UIBU TPNF PG UIFTF GVODUJPOT SFUVSO B SFTVMU
PG B MJTU UZQF 5IFZ UBLF B TUBSUJOH WBMVF BOE CVJME B MJTU XJUI
UIF TVDDFFEJOH JUFNT PG UIF TBNF UZQF
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

Prelude> enumFromTo 3 8
[3,4,5,6,7,8]
Prelude> enumFromTo 'a' 'f'
"abcdef"

'JOBMMZ MFUƊT UBLF B TIPSU MPPL BU enumFromThenTo

Prelude> enumFromThenTo 1 10 100


[1,10,19,28,37,46,55,64,73,82,91,100]

5BLF B MPPL BU UIF SFTVMUJOH MJTU BOE TFF JG ZPV DBO ƶOE UIF
QBUUFSO XIBU EPFT UIJT GVODUJPO EP 8IBU IBQQFOT JG XF HJWF
JU UIF WBMVFT 0 10 100 JOTUFBE )PX BCPVU 'a' 'c' 'z'

 4IPX
Show JT B UZQFDMBTT UIBU QSPWJEFT GPS UIF DSFBUJOH PG IVNBO
SFBEBCMF TUSJOH SFQSFTFOUBUJPOT PG TUSVDUVSFE EBUB ()$J VTFT
Show UP DSFBUF String WBMVFT JU DBO QSJOU JO UIF UFSNJOBM
Show JT OPU B TFSJBMJ[BUJPO GPSNBU 4FSJBMJ[BUJPO JT IPX EBUB
JT SFOEFSFE UP B UFYUVBM PS CJOBSZ GPSNBU GPS QFSTJTUFODF PS
DPNNVOJDBUJOH XJUI PUIFS DPNQVUFST PWFS B OFUXPSL "O
FYBNQMF PG QFSTJTUFODF XPVME CF TBWJOH EBUB UP B ƶMF PO EJTL
Show JT OPU TVJUBCMF GPS BOZ PG UIFTF QVSQPTFT JUƊT FYQSFTTMZ GPS
IVNBO SFBEBCJMJUZ
5IF UZQFDMBTT JOGPSNBUJPO MPPLT MJLF UIJT USVODBUFE

$)"15&3  -&44 "%)0$ 10-:.031)*4. 

class Show a where


showsPrec :: Int -> a -> ShowS
show :: a -> String
showList :: [a] -> ShowS

instance Show a => Show [a]


instance Show Ordering
instance Show a => Show (Maybe a)
instance Show Integer
instance Show Int
instance Show Char
instance Show Bool
instance Show ()
instance Show Float
instance Show Double

*NQPSUBOUMZ XF TFF UIBU WBSJPVT OVNCFS UZQFT Bool WBMVFT


UVQMFT BOE DIBSBDUFST BSF BMM BMSFBEZ JOTUBODFT PG Show 5IBU JT
UIFZ IBWF B EFƶOFE BCJMJUZ UP CF QSJOUFE UP UIF TDSFFO 5IFSF JT
BMTP B GVODUJPO show XIJDI UBLFT B QPMZNPSQIJD Ԑ BOE SFUVSOT
JU BT B String BMMPXJOH JU UP CF QSJOUFE

1SJOUJOH BOE TJEF FƵFDUT


8IFO ZPV BTL ()$J UP SFUVSO UIF SFTVMU PG BO FYQSFTTJPO BOE
QSJOU JU UP UIF TDSFFO ZPV BSF JOEJSFDUMZ JOWPLJOH B GVODUJPO
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

DBMMFE print UIBU XF FODPVOUFSFE CSJFƷZ JO UIF DIBQUFS BCPVU


QSJOUJOH BOE BHBJO JO UIF TFDUJPO BCPVU Ord BOE UIF FSSPS NFT
TBHF UIBU SFTVMUT GSPN QBTTJOH UIF max GVODUJPO UPP GFX BSHV
NFOUT "T VOEFSTUBOEJOH print JT JNQPSUBOU UP VOEFSTUBOEJOH
UIJT UZQFDMBTT XFƊSF HPJOH UP EJHSFTT B CJU BOE UBML BCPVU JU JO
NPSF EFUBJM
)BTLFMM JT B QVSF GVODUJPOBM QSPHSBNNJOH MBOHVBHF 5IF
ƌGVODUJPOBMƍ QBSU PG UIBU DPNFT GSPN UIF GBDU UIBU QSPHSBNT
BSF XSJUUFO BT GVODUJPOT TJNJMBS UP NBUIFNBUJDBM FRVBUJPOT JO
XIJDI BO PQFSBUJPO JT BQQMJFE UP TPNF BSHVNFOUT UP QSPEVDF
B SFTVMU 5IF ƌQVSFƍ QBSU PG PVS EFTDSJQUJPO PG )BTLFMM NFBOT
FYQSFTTJPOT JO )BTLFMM DBO CF FYQSFTTFE FYDMVTJWFMZ JO UFSNT
PG B MBNCEB DBMDVMVT
*U NBZ OPU TFFN PCWJPVT UIBU QSJOUJOH SFTVMUT UP UIF TDSFFO
DPVME CF B TPVSDF PG XPSSZ 5IF GVODUJPO JT OPU KVTU BQQMJFE
UP UIF BSHVNFOUT UIBU BSF JO JUT TDPQF CVU BMTP BTLFE UP BƵFDU
UIF XPSME PVUTJEF JUT TDPQF JO TPNF XBZ OBNFMZ CZ TIPXJOH
ZPV JUT SFTVMU PO B TDSFFO 5IJT JT LOPXO BT B TJEF FƵFDU B QP
UFOUJBMMZ PCTFSWBCMF SFTVMU BQBSU GSPN UIF WBMVF UIF FYQSFTTJPO
FWBMVBUFT UP )BTLFMM NBOBHFT FƵFDUT CZ TFQBSBUJOH FƵFDUGVM
DPNQVUBUJPOT GSPN QVSF DPNQVUBUJPOT JO XBZT UIBU QSFTFSWF
UIF QSFEJDUBCJMJUZ BOE TBGFUZ PG GVODUJPO FWBMVBUJPO *NQPS
UBOUMZ FƵFDUCFBSJOH DPNQVUBUJPOT UIFNTFMWFT CFDPNF NPSF
DPNQPTBCMF BOE FBTJFS UP SFBTPO BCPVU 5IF CFOFƶUT PG FY
QMJDJU FƵFDUT JODMVEF UIF GBDU UIBU JU NBLFT JU SFMBUJWFMZ FBTZ UP
SFBTPO BCPVU BOE QSFEJDU UIF SFTVMUT PG PVS GVODUJPOT
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

8IBU TFUT )BTLFMM BQBSU GSPN NPTU PUIFS GVODUJPOBM QSP


HSBNNJOH MBOHVBHFT JT UIBU JU JOUSPEVDFE BOE SFƶOFE B NFBOT
PG XSJUJOH PSEJOBSZ QSPHSBNT UIBU UBML UP UIF PVUTJEF XPSME
XJUIPVU BEEJOH BOZUIJOH UP UIF QVSF MBNCEB DBMDVMVT JU JT
GPVOEFE PO 5IJT QSPQFSUZ ƈ CFJOH MBNCEB DBMDVMVT BOE
OPUIJOH NPSF ƈ JT XIBU NBLFT )BTLFMM B QVSFMZ GVODUJPOBM
QSPHSBNNJOH MBOHVBHF
5IF print GVODUJPO JT TPNFUJNFT JOWPLFE JOEJSFDUMZ CZ ()$J
CVU JUT UZQF FYQMJDJUMZ SFWFBMT UIBU JU JT FƵFDUGVM 6Q UP OPX
XFƊWF CFFO DPWFSJOH PWFS IPX UIJT XPSLT CVU JUƊT UJNF UP EJWF
B CJU EFFQFS
print JT EFƶOFE JO UIF Prelude TUBOEBSE BT B GVODUJPO UP PVU
QVU ƌB WBMVF PG BOZ QSJOUBCMF UZQF UP UIF TUBOEBSE PVUQVU EFWJDF
1SJOUBCMF UZQFT BSF UIPTF UIBU BSF JOTUBODFT PG DMBTT Show QSJOU
DPOWFSUT WBMVFT UP TUSJOHT GPS PVUQVU VTJOH UIF TIPX PQFSBUJPO
BOE BEET B OFXMJOFƍ -FUƊT MPPL BU UIF UZQF PG print

Prelude> :t print
print :: Show a => a -> IO ()

"T XF TFF print UBLFT BO BSHVNFOU Ԑ UIBU JT BO JOTUBODF PG


UIF Show UZQFDMBTT BOE SFUVSOT BO IO () SFTVMU 5IJT SFTVMU JT BO
IO BDUJPO UIBU SFUVSOT B WBMVF PG UIF UZQF ()
8F TBX UIJT IO () SFTVMU QSFWJPVTMZ XIFO XF UBMLFE BCPVU
QSJOUJOH TUSJOHT 8F BMTP OPUFE UIBU JU JT UIF PCMJHBUPSZ UZQF
PG main JO B TPVSDF DPEF ƶMF 5IJT JT CFDBVTF SVOOJOH main POMZ
QSPEVDFT TJEF FƵFDUT
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

4UBUFE BT TJNQMZ BT QPTTJCMF BO *0 JOQVUPVUQVU GSFRVFOUMZ


XSJUUFO Ɖ*0Ɗ XJUIPVU B TMBTI XIFO SFGFSSJOH UP UIF )BTLFMM
EBUBUZQF UIFSF JT OP TMBTI
BDUJPO JT BO BDUJPO UIBU XIFO QFS
GPSNFE IBT TJEF FƵFDUT JODMVEJOH SFBEJOH GSPN JOQVU BOE
QSJOUJOH UP UIF TDSFFO BOE XJMM DPOUBJO B SFUVSO WBMVF 5IF
() EFOPUFT BO FNQUZ UVQMF XIJDI XF SFGFS UP BT VOJU 6OJU
JT B WBMVF BOE BMTP B UZQF UIBU IBT POMZ UIJT POF JOIBCJUBOU
UIBU FTTFOUJBMMZ SFQSFTFOUT OPUIJOH 1SJOUJOH B TUSJOH UP UIF
UFSNJOBM EPFTOƊU IBWF B NFBOJOHGVM SFUVSO WBMVF #VU BO IO
BDUJPO MJLF BOZ FYQSFTTJPO JO )BTLFMM DBOƊU SFUVSO OPUIJOH JU
NVTU SFUVSO TPNFUIJOH 4P XF VTF UIJT FNQUZ UVQMF UP SFQSF
TFOU UIF SFUVSO WBMVF BU UIF FOE PG PVS IO BDUJPO 5IBU JT UIF
print GVODUJPO XJMM ƶSTU EP UIF IO BDUJPO PG QSJOUJOH UIF TUSJOH
UP UIF UFSNJOBM BOE UIFO DPNQMFUF UIF IO BDUJPO NBSLJOH BO
FOE UP UIF FYFDVUJPO PG UIF GVODUJPO BOE B EFMJNJUBUJPO PG UIF
TJEF FƵFDUT CZ SFUVSOJOH UIJT FNQUZ OPUIJOH UVQMF *U EPFT
OPU QSJOU UIF FNQUZ UVQMF UP UIF TDSFFO CVU JU JT JNQMJDJUMZ
UIFSF 5IF TJNQMFTU XBZ UP UIJOL BCPVU UIF EJƵFSFODF CFUXFFO
B WBMVF XJUI B UZQJDBM UZQF MJLF String BOE UIF TBNF UZQF CVU
GSPN IO TVDI BT XJUI IO String JT UIBU IO BDUJPOT BSF GPSNVMBT
8IFO ZPV IBWF B WBMVF PG UZQF IO String JUƊT NPSF PG B NFBOT PG
QSPEVDJOH B String XIJDI NBZ SFRVJSF QFSGPSNJOH TJEF FƵFDUT
BMPOH UIF XBZ CFGPSF ZPV HFU ZPVS String WBMVF
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

-- this is just a String value


myVal :: String

-- this value is a method or means of obtaining


-- a value of type String which
-- performs side effects aka IO
ioString :: IO String

"O IO BDUJPO JT QFSGPSNFE XIFO XF DBMM main GPS PVS QSPHSBN


BT XF IBWF TFFO #VU XF BMTP QFSGPSN BO IO BDUJPO XIFO XF
JOWPLF print JNQMJDJUMZ PS FYQMJDJUMZ

8PSLJOH XJUI 4IPX


6Q UP OPX XF IBWF POMZ CFFO EFSJWJOH UZQFDMBTT JOTUBODFT
GPS Show CFDBVTF EFSJWJOH VTVBMMZ HJWFT VT UIF SFTVMU XF XBOU
XJUIPVU B MPU PG GVTT )BWJOH B Show JOTUBODF JT DSVDJBM UP CFJOH
BCMF UP QSJOU BOZUIJOH UP UIF UFSNJOBM TP XFƊSF HPJOH UP MPPL BU
TPNF FYBNQMFT PG XIZ Show JT JNQPSUBOU BOE IPX JU JT JNQMF
NFOUFE *OWPLJOH UIF Show UZQFDMBTT BMTP JOWPLFT JUT NFUIPET
TQFDJƶDBMMZ B NFUIPE PG UBLJOH ZPVS WBMVFT BOE UVSOJOH UIFN
JOUP WBMVFT UIBU DBO CF QSJOUFE UP UIF TDSFFO
" NJOJNBM JNQMFNFOUBUJPO PG BO JOTUBODF PG Show POMZ SF
RVJSFT UIBU show PS showsPrec CF JNQMFNFOUFE BT JO UIF GPMMPX
JOH FYBNQMF
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

data Mood = Blah

instance Show Mood where


show _ = "Blah"

*Main> Blah
Blah

)FSFƊT XIBU IBQQFOT JO ()$J XIFO ZPV EFƶOF B EBUBUZQF


BOE BTL ()$J UP TIPX JU XJUIPVU UIF JOTUBODF GPS UIF Show
UZQFDMBTT

Prelude> data Mood = Blah


Prelude> Blah

No instance for (Show Mood) arising


from a use of ‘print’
In a stmt of an interactive GHCi command: print it

/FYU MFUƊT MPPL BU IPX ZPV EFƶOF B EBUBUZQF UP IBWF BO JO


TUBODF PG Show 8F DBO EFSJWF UIF Show JOTUBODF GPS Mood CFDBVTF
JUƊT POF PG UIF UZQFDMBTTFT ()$ TVQQPSUT EFSJWJOH JOTUBODFT GPS
CZ EFGBVMU

Prelude> data Mood = Blah deriving Show


Prelude> Blah
Blah
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

"OE JO GBDU NPTU PG UIF UJNF UIBUƊT XIBU ZPVƊMM EP GPS ZPVS
PXO EBUBUZQFT *O UIF DIBQUFS PO CVJMEJOH QSPKFDUT XF XJMM
OFFE UP XSJUF B DVTUPN JOTUBODF GPS Show UIPVHI TP UIBU TIPVME
HJWF ZPV TPNFUIJOH FYDJUJOH UP MPPL GPSXBSE UP

 3FBE
5IF Read UZQFDMBTTXFMM JUƊTUIFSF :PVƊMM OPUJDF UIBU MJLF Show
B MPU PG UZQFT IBWF JOTUBODFT PG Read 5IJT UZQFDMBTT JT FTTFOUJBMMZ
UIF PQQPTJUF PG Show 8IFSF Show UBLFT UIJOHT BOE UVSOT UIFN
JOUP IVNBOSFBEBCMF TUSJOHT Read UBLFT TUSJOHT BOE UVSOT UIFN
JOUP UIJOHT -JLF Show JUƊT OPU B TFSJBMJ[BUJPO GPSNBU 4P XIBUƊT
UIF QSPCMFN 8F HBWF UIBU EJSF XBSOJOH BHBJOTU VTJOH Read
FBSMJFS JO UIF DIBQUFS CVU UIJT EPFTOƊU TFFN MJLF B CJH EFBM
SJHIU
5IF QSPCMFN JT JO UIF String UZQF " String JT B MJTU XIJDI
DPVME CF FNQUZ JO TPNF DBTFT PS TUSFUDI PO UP JOƶOJUZ JO PUIFS
DBTFT
8F DBO CFHJO UP VOEFSTUBOE UIJT CZ FYBNJOJOH UIF UZQFT

Prelude> :t read
read :: Read a => String -> a

5IFSFƊT OP XBZ Read a => String -> a XJMM BMXBZT XPSL -FUƊT
DPOTJEFS B UZQF MJLF Integer XIJDI IBT B Read JOTUBODF 8F BSF JO
OP XBZ HVBSBOUFFE UIBU UIF String XJMM CF B WBMJE SFQSFTFOUBUJPO
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

PG BO Integer WBMVF " String WBMVF DBO CF BOZ UFYU 5IBUƊT XBZ
UPP CJH PG B UZQF GPS UIJOHT XF XBOU UP QBSTF JOUP OVNCFST
8F DBO QSPWF UIJT GPS PVSTFMWFT JO UIF 3&1-

Prelude> read "1234567" :: Integer


1234567
Prelude> read "BLAH" :: Integer
*** Exception: Prelude.read: no parse

5IBU FYDFQUJPO JT B SVOUJNF FSSPS BOE NFBOT UIBU read JT B


QBSUJBM GVODUJPO B GVODUJPO UIBU EPFTOƊU SFUVSO B QSPQFS WBMVF
BT B SFTVMU GPS BMM QPTTJCMF JOQVUT 8F IBWF XBZT PG DMFBOJOH
UIJT VQ XFƊMM FYQMBJO BOE EFNPOTUSBUF MBUFS 8F TIPVME TUSJWF
UP BWPJE XSJUJOH PS VTJOH TVDI GVODUJPOT JO )BTLFMM CFDBVTF
)BTLFMM HJWFT VT UIF UPPMT OFDFTTBSZ UP BWPJE TFOTFMFTT TPVSDFT
PG FSSPST JO PVS DPEF

 *OTUBODFT BSF EJTQBUDIFE CZ UZQF


8FƊWF TBJE B GFX UJNFT XJUIPVU FYQMBJOJOH JU UIBU UZQFDMBTTFT
BSF EJTQBUDIFE CZ UZQF CVU JUƊT BO JNQPSUBOU UIJOH UP VOEFS
TUBOE 5ZQFDMBTTFT BSF EFƶOFE CZ UIF TFU PG PQFSBUJPOT BOE
WBMVFT BMM JOTUBODFT XJMM QSPWJEF 5ZQFDMBTT JOTUBODFT BSF VOJRVF
QBJSJOHT PG UIF UZQFDMBTT BOE B UZQF 5IFZ EFƶOF UIF XBZT UP
JNQMFNFOU UIF UZQFDMBTT NFUIPET GPS UIBU UZQF
8FƊSF HPJOH UP XBML UISPVHI TPNF DPEF UP JMMVTUSBUF XIBU
UIJT BMM NFBOT 5IF ƶSTU UIJOH ZPV XJMM TFF JT UIBU XFƊWF XSJUUFO
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

PVS PXO UZQFDMBTT BOE JOTUBODFT GPS EFNPOTUSBUJPO QVSQPTFT


8F XJMM UBML BCPVU IPX UP XSJUF ZPVS PXO UZQFDMBTTFT MBUFS JO
UIF CPPL 5IPTF EFUBJMT BSFOƊU JNQPSUBOU GPS VOEFSTUBOEJOH
UIJT DPEF +VTU SFNFNCFS

Ƒ B UZQFDMBTT EFƶOFT B TFU PG GVODUJPOT BOEPS WBMVFT

Ƒ UZQFT IBWF JOTUBODFT PG UIBU UZQFDMBTT

Ƒ UIF JOTUBODFT TQFDJGZ UIF XBZT UIBU UZQF VTFT UIF GVODUJPOT
PG UIF UZQFDMBTT

5IJT JT WBDVPVT BOE TJMMZ 5IJT JT POMZ UP NBLF B QPJOU 1MFBTF


EP OPU XSJUF UZQFDMBTTFT MJLF UIJT

class Numberish a where


fromNumber :: Integer -> a
toNumber :: a -> Integer

-- pretend newtype is data for now


newtype Age =
Age Integer
deriving (Eq, Show)

instance Numberish Age where


fromNumber n = Age n
toNumber (Age n) = n
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

newtype Year =
Year Integer
deriving (Eq, Show)

instance Numberish Year where


fromNumber n = Year n
toNumber (Year n) = n

5IFO TVQQPTF XF XSJUF B GVODUJPO VTJOH UIJT UZQFDMBTT BOE


UIF UXP UZQFT BOE JOTUBODFT

sumNumberish :: Numberish a => a -> a -> a


sumNumberish a a' = fromNumber summed
where integerOfA = toNumber a
integerOfAPrime = toNumber a'
summed = integerOfA + integerOfAPrime

/PX MFU VT UIJOL BCPVU UIJT GPS B NPNFOU 5IF DMBTT EFG
JOJUJPO PG Numberish EPFTOƊU EFƶOF BOZ UFSNT PS BDUVBM DPEF XF
DBO DPNQJMF BOE FYFDVUF POMZ UZQFT 5IF DPEF BDUVBMMZ MJWFT
JO UIF JOTUBODFT GPS Age BOE Year 4P IPX EPFT )BTLFMM LOPX
XIFSF UP ƶOE DPEF

Prelude> sumNumberish (Age 10) (Age 10)


Age 20
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

*O UIF BCPWF JU LOFX UP VTF UIF JOTUBODF PG Numberish GPS Age


CFDBVTF JU DPVME TFF UIBU PVS BSHVNFOUT UP sumNumberish XFSF
PG UZQF Age 8F DBO TFF UIJT XJUI UIF UZQF JOGFSFODF UPP

Prelude> :t sumNumberish
sumNumberish :: Numberish a => a -> a -> a

Prelude> :t sumNumberish (Age 10)


sumNumberish (Age 10) :: Age -> Age

"ǒFS UIF ƶSTU QBSBNFUFS JT BQQMJFE UP B WBMVF PG UZQF Age JU


LOPXT UIBU BMM PUIFS PDDVSSFODFT PG UZQF Numberish a => a NVTU
BDUVBMMZ CF Age
5P TFF B DBTF XIFSF XFƊSF OPU QSPWJEJOH FOPVHI JOGPSNBUJPO
UP )BTLFMM GPS JU UP JEFOUJGZ B DPODSFUF UZQF XJUI XIJDI UP HFU
UIF BQQSPQSJBUF JOTUBODF XFƊSF HPJOH UP DIBOHF PVS UZQFDMBTT
BOE BTTPDJBUFE JOTUBODFT

-- This is even worse than the last one.


-- Don't use typeclasses to define default values.
-- Seriously. Haskell Ninjas will find you
-- and replace your toothpaste with muddy chalk.

class Numberish a where


fromNumber :: Integer -> a
toNumber :: a -> Integer
defaultNumber :: a
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

instance Numberish Age where


fromNumber n = Age n
toNumber (Age n) = n
defaultNumber = Age 65

instance Numberish Year where


fromNumber n = Year n
toNumber (Year n) = n
defaultNumber = Year 1988

5IFO JO UIF 3&1- XF DBO TFF UIBU JO TPNF DBTFT UIFSFƊT OP


XBZ GPS )BTLFMM UP LOPX XIBU XF XBOU

Prelude> defaultNumber

No instance for (Show a0) arising


from a use of ‘print’
The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
instance Show a => Show (Maybe a)
instance Show Ordering
instance Show Integer
...plus 24 others

5IJT GBJMT CFDBVTF JU IBT OP JEFB XIBU UZQF defaultNumber JT


PUIFS UIBO UIBU JUƊT QSPWJEFE GPS CZ NumberishƊT JOTUBODFT #VU
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

UIF HPPE OFXT JT FWFO JG JUƊT B WBMVF BOE EPFTOƊU UBLF BOZ BSHV
NFOUT XF IBWF B NFBOT PG UFMMJOH )BTLFMM XIBU XF XBOU

Prelude> defaultNumber :: Age


Age 65
Prelude> defaultNumber :: Year
Year 1988

+VTU BTTJHO UIF UZQF ZPV FYQFDU BOE JU XPSLT ƶOF )FSF
)BTLFMM JT VTJOH UIF UZQF BTTFSUJPO UP EJTQBUDI PS TQFDJGZ XIBU
UZQFDMBTT JOTUBODF XF XBOU UP HFU PVS defaultNumber GSPN

8IZ OPU XSJUF B UZQFDMBTT MJLF UIJT 'PS SFBTPOT XFƊMM FYQMBJO
XIFO XF UBML BCPVU Monoid JUƊT JNQPSUBOU UIBU ZPVS UZQFDMBTTFT
IBWF MBXT BOE SVMFT BCPVU IPX UIFZ XPSL Numberish JT B CJU
BSCJUSBSZ 5IFSF BSF CFUUFS XBZT UP FYQSFTT XIBU JU EPFT JO
)BTLFMM UIBO B UZQFDMBTT 'VODUJPOT BOE WBMVFT BMPOF TVƸDF
IFSF

 (JNNF NPSF PQFSBUJPOT


8F UBMLFE BCPVU UIF EJƵFSFOU LJOET PG QPMZNPSQIJTN JO UZQF
TJHOBUVSFT ƈ DPOTUSBJOFE WFSTVT QBSBNFUSJD )BWJOH OP DPO
TUSBJOU PO PVS UFSNMFWFM WBMVFT NFBOT UIFZ DPVME CF BOZ UZQF
CVU UIFSF JTOƊU NVDI XF DBO EP XJUI UIFN 5IF NFUIPET BOE
PQFSBUJPOT BSF JO UIF UZQFDMBTTFT BOE TP XF HFU NPSF VUJMJUZ
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

CZ TQFDJGZJOH UZQFDMBTT DPOTUSBJOUT *G ZPVS UZQFT BSF NPSF


HFOFSBM UIBO ZPVS UFSNT BSF UIFO ZPV OFFE UP DPOTUSBJO ZPVS
UZQFT XJUI UIF UZQFDMBTTFT UIBU QSPWJEF UIF PQFSBUJPOT ZPV
XBOU UP VTF 8F MPPLFE BU TPNF FYBNQMFT PG UIJT JO UIF TFD
UJPOT BCPWF BCPVU Integral BOE Fractional CVU JO UIJT TFDUJPO
XFƊMM CF NPSF TQFDJƶD BCPVU IPX UP NPEJGZ UZQF TJHOBUVSFT UP
ƶU UIF UFSNT
8FƊMM TUBSU CZ MPPLJOH BU TPNF FYBNQMFT PG UJNFT XIFO XF
OFFE UP DIBOHF PVS UZQFT CFDBVTF UIFZƊSF NPSF HFOFSBM UIBO
PVS UFSNT BMMPX

add :: a -> a -> a


add x y = x + y

*G ZPV MPBE JU VQ ZPVƊMM HFU UIF GPMMPXJOH FSSPS

No instance for (Num a) arising from a use of ‘+’


Possible fix:
add (Num a) to the context of
the type signature for add :: a -> a -> a

'PSUVOBUFMZ UIJT JT POF PG UIPTF DBTFT XIFSF ()$ LOPXT


QSFDJTFMZ XIBU UIF QSPCMFN JT BOE IPX UP SFNFEZ JU 8F KVTU
OFFE UP BEE B Num DPOTUSBJOU UP UIF UZQF Ԑ #VU XIZ #FDBVTF
PVS GVODUJPO DBOƊU BDDFQU B WBMVF PG TUSJDUMZ BOZ UZQF 8F OFFE
TPNFUIJOH UIBU IBT BO JOTUBODF PG Num CFDBVTF UIF (+) GVODUJPO
DPNFT GSPN Num
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

add :: Num a => a -> a -> a


add x y = x + y

8JUI UIF DPOTUSBJOU BEEFE UP UIF UZQF JU XPSLT ƶOF 8IBU


JG XF VTF B NFUIPE GSPN BOPUIFS PQFSBUJPO

addWeird :: Num a => a -> a -> a


addWeird x y =
if x > 1
then x + y
else x

8F HFU BOPUIFS FSSPS CVU PODF BHBJO ()$ IFMQT VT PVU TP


MPOH BT XF SFTJTU UIF QVMM PG UVOOFM WJTJPO BOE MPPL BU XIBU JUƊT
UFMMJOH VT

Could not deduce (Ord a) arising from a use of ‘>’


from the context (Num a)
bound by the type signature for
addWeird :: Num a => a -> a -> a

Possible fix:
add (Ord a) to the context of
the type signature for
addWeird :: Num a => a -> a -> a

"MM QSPHSBNNFST FYQFSJFODF UIJT +VTU TMPX EPXO BOE ZPVƊMM CF PLBZ
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

5IF QSPCMFN JT UIBU IBWJOH B Num DPOTUSBJOU PO PVS UZQF Ԑ


JTOƊU FOPVHI Num EPFTOƊU JNQMZ Ord (JWFO UIBU XF IBWF UP BEE
BOPUIFS DPOTUSBJOU XIJDI JT XIBU ()$ UPME VT UP EP

addWeird :: (Ord a, Num a) => a -> a -> a


addWeird x y =
if x > 1
then x + y
else x

/PX UIJT TIPVME UZQFDIFDL CFDBVTF PVS DPOTUSBJOUT BSF BTL


JOH UIBU Ԑ IBWF JOTUBODFT PG Num BOE Ord

$PODSFUF UZQFT JNQMZ BMM UIF UZQFDMBTTFT UIFZ


QSPWJEF
8FƊMM CF SFQVSQPTJOH TPNF FYBNQMFT GSPN FBSMJFS JO UIF DIBQ
UFS NPEJGZJOH UIFN UP BMM IBWF B DPODSFUF UZQF JO UIF QMBDF PG
Ԑ
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

add :: Int -> Int -> Int


add x y = x + y

addWeird :: Int -> Int -> Int


addWeird x y =
if x > 1
then x + y
else x

check' :: Int -> Int -> Bool


check' a a' = a == a'

5IFTF XJMM BMM UZQFDIFDL 5IJT JT CFDBVTF UIF Int UZQF IBT
UIF UZQFDMBTTFT Num Eq BOE Ord BMM JNQMFNFOUFE 8F EPOƊU OFFE
UP TBZ Ord Int => Int -> Int -> Int CFDBVTF JU EPFTOƊU BEE BOZ
JOGPSNBUJPO " DPODSFUF UZQF FJUIFS IBT B UZQFDMBTT JOTUBODF PS
JU EPFTOƊU ƈ BEEJOH UIF DPOTUSBJOU NFBOT OPUIJOH " DPODSFUF
UZQF BMXBZT JNQMJFT UIF UZQFDMBTTFT UIBU BSF QSPWJEFE GPS JU
5IFSF BSF TPNF DBWFBUT UP LFFQ JO NJOE IFSF XIFO JU DPNFT
UP VTJOH DPODSFUF UZQFT 0OF PG UIF OJDF UIJOHT BCPVU QBSB
NFUSJDJUZ BOE UZQFDMBTTFT JT UIBU ZPV BSF CFJOH FYQMJDJU BCPVU
XIBU ZPV NFBO UP EP XJUI ZPVS EBUB XIJDI NFBOT ZPV BSF
MFTT MJLFMZ UP NBLF B NJTUBLF Int JT B CJH EBUBUZQF XJUI NBOZ
JOIBCJUBOUT BOE NBOZ UZQFDMBTTFT BOE PQFSBUJPOT EFƶOFE GPS
JU ƈ JU DPVME CF FBTZ UP NBLF B GVODUJPO UIBU EPFT TPNFUIJOH
VOJOUFOEFE 8IFSFBT JG XF XFSF UP XSJUF B GVODUJPO FWFO JG XF
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

IBE Int WBMVFT JO NJOE GPS JU XIJDI VTFE B QPMZNPSQIJD UZQF


DPOTUSBJOFE CZ UIF UZQFDMBTT JOTUBODFT XF XBOUFE XF DPVME
FOTVSF XF POMZ VTFE UIF PQFSBUJPOT XF JOUFOEFE 5IJT JTOƊU B
QBOBDFB CVU JU DBO CF XPSUI BWPJEJOH DPODSFUF UZQFT GPS UIFTF
BOE PUIFS
SFBTPOT TPNFUJNFT

 $IBQUFS &YFSDJTFT


.VMUJQMF DIPJDF
 5IF &R DMBTT

B
JODMVEFT BMM UZQFT JO )BTLFMM
C
JT UIF TBNF BT UIF 0SE DMBTT
D
NBLFT FRVBMJUZ UFTUT QPTTJCMF
E
POMZ JODMVEFT OVNFSJD UZQFT

 5IF UZQFDMBTT 0SE

B
BMMPXT BOZ UXP WBMVFT UP CF DPNQBSFE
C
JT B TVCDMBTT PG &R
D
JT B TVQFSDMBTT PG &R
E
IBT OP JOTUBODF GPS #PPM

 4VQQPTF UIF UZQFDMBTT 0SE IBT BO PQFSBUPS > 8IBU JT UIF


UZQF PG >
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

B
Ord a => a -> a -> Bool
C
Ord a => Int -> Bool
D
Ord a => a -> Char
E
Ord a => Char -> [Char]

 *O x = divMod 16 12

B
UIF UZQF PG ԧ JT *OUFHFS
C
UIF WBMVF PG ԧ JT VOEFDJEBCMF
D
UIF UZQF PG ԧ JT B UVQMF
E
ԧ JT FRVBM UP 12 / 16

 5IF UZQFDMBTT *OUFHSBM JODMVEFT

B
*OU BOE *OUFHFS OVNCFST
C
JOUFHSBM SFBM BOE GSBDUJPOBM OVNCFST
D
4DISPEJOHFSƊT DBU
E
POMZ QPTJUJWF OVNCFST

%PFT JU UZQFDIFDL
'PS UIJT TFDUJPO PG FYFSDJTFT ZPVƊMM CF QSBDUJDJOH MPPLJOH GPS
UZQF BOE UZQFDMBTT FSSPST
'PS FYBNQMF printIt XJMM OPU XPSL CFDBVTF GVODUJPOT MJLF
ԧ IBWF OP JOTUBODF PG Show UIF UZQFDMBTT UIBU MFUT ZPV DPOWFSU
UIJOHT UP 4USJOHT VTVBMMZ GPS QSJOUJOH

$)"15&3  -&44 "%)0$ 10-:.031)*4. 

x :: Int -> Int


x blah = blah + 20

printIt :: IO ()
printIt = putStrLn (show x)

)FSFƊT UIF UZQF FSSPS ZPV HFU JG ZPV USZ UP MPBE UIF DPEF

No instance for (Show (Int -> Int)) arising


from a use of ‘show’

In the first argument of ‘putStrLn’, namely ‘(show x)’


In the expression: putStrLn (show x)
In an equation for ‘printIt’: printIt = putStrLn (show x)

*UƊT TBZJOH JU DBOƊU ƶOE BO JNQMFNFOUBUJPO PG UIF UZQFDMBTT


Show GPS UIF UZQF Int -> Int XIJDI NBLFT TFOTF /PUIJOH XJUI
UIF GVODUJPO UZQF DPOTUSVDUPS (->) IBT BO JOTUBODF PG Show CZ
EFGBVMU JO )BTLFMM
&YBNJOF UIF GPMMPXJOH DPEF BOE EFDJEF XIFUIFS JU XJMM UZQF
DIFDL 5IFO MPBE JU JO ()$J BOE TFF JG ZPV XFSF DPSSFDU *G
JU EPFTOƊU UZQFDIFDL USZ UP NBUDI UIF UZQF FSSPS BHBJOTU ZPVS
VOEFSTUBOEJOH PG XIZ JU EJEOƊU XPSL *G ZPV DBO ƶY UIF FSSPS
BOE SFSVO UIF DPEF

'PS BO FYQMBOBUJPO BOE KVTUJƶDBUJPO PG XIZ GVODUJPOT JO )BTLFMM DBOOPU IBWF B
Show JOTUBODF TFF UIF XJLJ QBHF PO UIJT UPQJD https://wiki.haskell.org/Show_instance_for_
functions
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

 %PFT UIF GPMMPXJOH DPEF UZQFDIFDL *G OPU XIZ OPU

data Person = Person Bool

printPerson :: Person -> IO ()


printPerson person = putStrLn (show person)

 %PFT UIF GPMMPXJOH UZQFDIFDL *G OPU XIZ OPU

data Mood = Blah


| Woot deriving Show

settleDown x = if x == Woot
then Blah
else x

 *G ZPV XFSF BCMF UP HFU settleDown UP UZQFDIFDL

B
8IBU WBMVFT BSF BDDFQUBCMF JOQVUT UP UIBU GVODUJPO
C
8IBU XJMM IBQQFO JG ZPV USZ UP SVO settleDown 9 8IZ
D
8IBU XJMM IBQQFO JG ZPV USZ UP SVO Blah > Woot 8IZ

 %PFT UIF GPMMPXJOH UZQFDIFDL *G OPU XIZ OPU


$)"15&3  -&44 "%)0$ 10-:.031)*4. 

type Subject = String


type Verb = String
type Object = String

data Sentence =
Sentence Subject Verb Object
deriving (Eq, Show)

s1 = Sentence "dogs" "drool"


s2 = Sentence "Julie" "loves" "dogs"

(JWFO B EBUBUZQF EFDMBSBUJPO XIBU DBO XF EP


(JWFO UIF GPMMPXJOH EBUBUZQF EFƶOJUJPOT

data Rocks =
Rocks String deriving (Eq, Show)

data Yeah =
Yeah Bool deriving (Eq, Show)

data Papu =
Papu Rocks Yeah
deriving (Eq, Show)
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

8IJDI PG UIF GPMMPXJOH XJMM UZQFDIFDL 'PS UIF POFT UIBU


EPOƊU UZQFDIFDL XIZ EPOƊU UIFZ

 phew = Papu "chases" True

 truth = Papu (Rocks "chomskydoz")


(Yeah True)

 equalityForall :: Papu -> Papu -> Bool


equalityForall p p' = p == p'

 comparePapus :: Papu -> Papu -> Bool


comparePapus p p' = p > p'

.BUDI UIF UZQFT


8FƊSF HPJOH UP HJWF ZPV UXP UZQFT BOE UIFJS JNQMFNFOUBUJPOT
5IFO XFƊSF HPJOH UP BTL ZPV JG ZPV DBO TVCTUJUVUF UIF TFDPOE
UZQF GPS UIF ƶSTU :PV DBO UFTU UIJT CZ UZQJOH UIF ƶSTU EFDMBSBUJPO
BOE JUT UZQF JOUP B ƶMF BOE FEJUJOH JO UIF OFX POF MPBEJOH UP
TFF JG JU GBJMT %POƊU KVTU HVFTT UFTU BMM ZPVS BOTXFST

 'PS UIF GPMMPXJOH EFƶOJUJPO

B
i :: Num a => a
i = 1

C
5SZ SFQMBDJOH UIF UZQF TJHOBUVSF XJUI UIF GPMMPXJOH
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

i :: a
"ǒFS ZPVƊWF GPSNVMBUFE ZPVS PXO BOTXFS UIFO UFTUFE
UIBU BOTXFS BOE CFMJFWF ZPV VOEFSTUBOE XIZ ZPV XFSF
SJHIU PS XSPOH NBLF TVSF UP VTF ()$J UP DIFDL XIBU
UZQF ()$ JOGFST GPS UIF EFƶOJUJPOT XF QSPWJEF XJUIPVU
B UZQF BTTJHOFE 'PS FYBNQMF GPS UIJT POF ZPVƊE UZQF
JO

Prelude> let i = 1
Prelude> :t i
-- Result elided intentionally.

 B
f :: Float
f = 1.0

C
f :: Num a => a

 B
f :: Float
f = 1.0

C
f :: Fractional a => a

 )JOU GPS UIF GPMMPXJOH UZQF :info RealFrac JO ZPVS 3&1-

B
f :: Float
f = 1.0

C
f :: RealFrac a => a
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

 B
freud :: a -> a
freud x = x

C
freud :: Ord a => a -> a

 B
freud' :: a -> a
freud' x = x

C
freud' :: Int -> Int

 B
myX = 1 :: Int

sigmund :: Int -> Int


sigmund x = myX

C
sigmund :: a -> a

 B
myX = 1 :: Int
sigmund' :: Int -> Int
sigmund' x = myX

C
sigmund' :: Num a => a -> a

 B
:PVƊMM OFFE UP JNQPSU sort GSPN Data.List
jung :: Ord a => [a] -> a
jung xs = head (sort xs)
C
jung :: [Int] -> Int

 B
young :: [Char] -> Char
young xs = head (sort xs)
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

C
young :: Ord a => [a] -> a

 B
mySort :: [Char] -> [Char]
mySort = sort

signifier :: [Char] -> Char


signifier xs = head (mySort xs)

C
signifier :: Ord a => [a] -> a

5ZQF,XPO%P 5XP &MFDUSJD 5ZQFBMPP


3PVOE 5XP 4BNF SVMFT BQQMZ ƈ ZPVƊSF USZJOH UP ƶMM JO UFSNT
DPEF
XIJDIƊMM ƶU UIF UZQF 5IF JEFB XJUI UIFTF FYFSDJTFT JT UIBU
ZPVƊMM EFSJWF UIF JNQMFNFOUBUJPO GSPN UIF UZQF JOGPSNBUJPO
:PVƊMM QSPCBCMZ OFFE UP VTF TUVƵ GSPN 1SFMVEF

 chk :: Eq b => (a -> b) -> a -> b -> Bool


chk = ???

 -- Hint: use some arithmetic operation to


-- combine values of type 'b'. Pick one.
arith :: Num b => (a -> b) -> Integer -> a -> b
arith = ???
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

 $IBQUFS %FƶOJUJPOT


 5ZQFDMBTT JOIFSJUBODF JT XIFO B UZQFDMBTT IBT B TVQFSDMBTT
5IJT JT B XBZ PG FYQSFTTJOH UIBU B UZQFDMBTT SFRVJSFT BOPUIFS
UZQFDMBTT UP CF BWBJMBCMF GPS B HJWFO UZQF CFGPSF ZPV DBO
XSJUF BO JOTUBODF

class Num a => Fractional a where


(/) :: a -> a -> a
recip :: a -> a
fromRational :: Rational -> a

)FSF UIF UZQFDMBTT Fractional JOIFSJUT GSPN Num 8F DPVME


BMTP TBZ UIBU Num JT B TVQFSDMBTT PG Fractional 5IF MPOH
BOE TIPSU PG JU JT UIBU JG ZPV XBOU UP XSJUF BO JOTUBODF PG
Fractional GPS TPNF Ԑ UIBU UZQF Ԑ NVTU BMSFBEZ IBWF BO
JOTUBODF PG Num CFGPSF ZPV NBZ EP TP
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

-- Even though in principle


-- this could work, it will fail because
-- Nada doesn't have a Num instance

newtype Nada = Nada Double deriving (Eq, Show)

instance Fractional Nada where


(Nada x) / (Nada y) = Nada (x / y)
recip (Nada n) = Nada (recip n)
fromRational r = Nada (fromRational r)

5IFO JG ZPV USZ UP MPBE JU

No instance for (Num Nada)


arising from the superclasses
of an instance declaration
In the instance declaration for
‘Fractional Nada’

:PV OFFE B Num JOTUBODF ƶSTU $BOƊU XSJUF POF UIBU NBLFT
TFOTF 5IFO ZPVƊSF OPU BMMPXFE UP IBWF B Fractional JO
TUBODF FJUIFS 5IFNƊT UIF SVMFT

 4JEF FƵFDUT BSF IPX XF SFGFS UP PCTFSWBCMF BDUJPOT QSPHSBNT


NBZ UBLF PUIFS UIBO DPNQVUF B WBMVF *G B GVODUJPO NPE
JƶFT TPNF TUBUF PS JOUFSBDUT XJUI UIF PVUTJEF XPSME JO B
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

NBOOFS UIBU DBO CF PCTFSWFE UIFO XF TBZ JU IBT BO FƵFDU


PO UIF XPSME

 *0 JT UIF UZQF GPS WBMVFT XIPTF FWBMVBUJPO CFBST UIF QPTTJ


CJMJUZ PG DBVTJOH TJEF FƵFDUT TVDI BT QSJOUJOH UFYU SFBEJOH
UFYU JOQVU GSPN UIF VTFS SFBEJOH PS XSJUJOH ƶMFT PS DPO
OFDUJOH UP SFNPUF DPNQVUFST 5IJT XJMM CF FYQMBJOFE JO
NVDI NPSF EFQUI JO UIF DIBQUFS PO IO

 "O JOTUBODF JT UIF EFƶOJUJPO PG IPX B UZQFDMBTT TIPVME


XPSL GPS B HJWFO UZQF *OTUBODFT BSF VOJRVF GPS B HJWFO
DPNCJOBUJPO PG UZQFDMBTT BOE UZQF

 *O )BTLFMM XF IBWF EFSJWFE JOTUBODFT TP UIBU PCWJPVT PS DPN


NPO UZQFDMBTTFT TVDI BT Eq Enum Ord BOE Show DBO IBWF
UIF JOTUBODFT HFOFSBUFE CBTFE POMZ PO IPX UIF EBUBUZQF
JT EFƶOFE 5IJT JT TP QSPHSBNNFST DBO NBLF VTF PG UIFTF
DPOWFOJFODFT XJUIPVU XSJUJOH UIF DPEF UIFNTFMWFT PWFS
BOE PWFS
$)"15&3  -&44 "%)0$ 10-:.031)*4. 

 5ZQFDMBTT JOIFSJUBODF QBSUJBM


5IJT JT OPU B DPNQMFUF DIBSU PG UZQFDMBTT JOIFSJUBODF *U JMMVT
USBUFT UIF SFMBUJPOTIJQ CFUXFFO B GFX PG UIF UZQFDMBTTFT XFƊWF
UBMLFE BCPVU JO UIJT DIBQUFS :PV DBO TFF GPS FYBNQMF UIBU
UIF TVCDMBTT Fractional JOIFSJUT GSPN UIF TVQFSDMBTT Num CVU OPU
WJDF WFSTB 8IJMF NBOZ UZQFT IBWF JOTUBODFT PG Show BOE Read
UIFZ BSFOƊU TVQFSDMBTTFT TP XFƊWF MFǒ UIFN PVU PG UIF DIBSU GPS
DMBSJUZ

 'PMMPXVQ SFTPVSDFT


 1 8BEMFS BOE 4 #MPUU )PX UP NBLF BEIPD QPMZNPS
QIJTN MFTT BE IPD
http://www.cse.iitk.ac.in/users/karkare/courses/2010/cs653/
Papers/ad-hoc-polymorphism.pdf

 $PSEFMJB 7 )BMM ,FWJO )BNNPOE 4JNPO - 1FZUPO +POFT


$)"15&3  -&44 "%)0$ 10-:.031)*4. 

BOE 1IJMJQ - 8BEMFS 5ZQFDMBTTFT JO )BTLFMM


http://ropas.snu.ac.kr/lib/dock/HaHaJoWa1996.pdf
$IBQUFS 

.PSF GVODUJPOBM QBUUFSOT

* XPVME MJLF UP CF BCMF UP


BMXBZTƒEJWJEF UIF UIJOHT
VQ JOUP BT NBOZ QJFDFT BT
* DBO FBDI PG XIJDI *
VOEFSTUBOE TFQBSBUFMZ *
XPVME MJLF UP VOEFSTUBOE
UIF XBZ PG BEEJOH UIJOHT
VQ JOEFQFOEFOUMZ PG
XIBU JU JT *ƊN BEEJOH VQ

(FSBME 4VTTNBO


$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 .BLF JU GVODZ


:PV NJHIU CF BTLJOH ZPVSTFMG XIBU UIJT DIBQUFS JT BMM BCPVU
IBWFOƊU XF CFFO UBMLJOH BCPVU GVODUJPOT BMM BMPOH 8F IBWF
CVU BT ZPV NJHIU HVFTT GSPN UIF GBDU UIBU )BTLFMM JT B GVODUJPOBM
QSPHSBNNJOH MBOHVBHF UIFSF JT NPSF UP TBZ ƈ TP NVDI NPSF
" GVODUJPO JT BO JOTUSVDUJPO GPS QSPEVDJOH BO PVUQVU GSPN
BO JOQVU PS BSHVNFOU 'VODUJPOT BSF BQQMJFE UP BSHVNFOUT
XIJDI CJOET UIFJS QBSBNFUFST UP WBMVFT 5IF GVMMZ BQQMJFE
GVODUJPO XJUI JUT BSHVNFOUT JT UIFO FWBMVBUFE UP QSPEVDF UIF
PVUQVU PS SFTVMU *O UIJT DIBQUFS XF XJMM EFNPOTUSBUF

Ƒ )BTLFMM GVODUJPOT BSF ƶSTUDMBTT FOUJUJFT UIBU

Ƒ DBO CF WBMVFT JO FYQSFTTJPOT MJTUT PS UVQMFT

Ƒ DBO CF QBTTFE BT BSHVNFOUT UP B GVODUJPO

Ƒ DBO CF SFUVSOFE GSPN B GVODUJPO BT B SFTVMU

Ƒ NBLF VTF PG TZOUBDUJD QBUUFSOT

 "SHVNFOUT BOE QBSBNFUFST


"T ZPV LOPX GSPN PVS EJTDVTTJPO PG DVSSZJOH GVODUJPOT JO
)BTLFMM NBZ BQQFBS UP IBWF NVMUJQMF QBSBNFUFST CVU UIJT JT
POMZ UIF TVSGBDF BQQFBSBODF JO GBDU BMM GVODUJPOT UBLF POF
BSHVNFOU BOE SFUVSO POF SFTVMU 8F DPOTUSVDU GVODUJPOT JO
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

)BTLFMM UISPVHI WBSJPVT TZOUBDUJD NFBOT PG EFOPUJOH UIBU BO


FYQSFTTJPO UBLFT BSHVNFOUT 'VODUJPOT BSF EFƶOFE CZ UIF GBDU
UIBU UIFZ DBO CF BQQMJFE UP BO BSHVNFOU BOE SFUVSO B SFTVMU
"MM )BTLFMM WBMVFT DBO CF BSHVNFOUT UP GVODUJPOT " WBMVF
UIBU DBO CF VTFE BT BO BSHVNFOU UP B GVODUJPO JT B ƶSTUDMBTT
WBMVF *O )BTLFMM UIJT JODMVEFT GVODUJPOT XIJDI DBO CF BSHV
NFOUT UP NPSF GVODUJPOT TUJMM /PU BMM QSPHSBNNJOH MBOHVBHFT
BMMPX UIJT CVU IPQFGVMMZ UIF FBSMJFS EJTDVTTJPO PG UIF GVODUJPO
UZQF BOE DVSSZJOH IBWF HJWFO BO JEFB PG IPX BOE XIZ UIJT
XPSLT

%FDMBSJOH QBSBNFUFST
:PV OBNF QBSBNFUFST UP GVODUJPOT JO )BTLFMM CZ EFDMBSJOH
UIFN CFUXFFO UIF OBNF PG UIF GVODUJPO XIJDI JT BMXBZT BU
UIF MFǒ NBSHJO BOE UIF FRVBMT TJHO TFQBSBUJOH UIF OBNF GSPN
CPUI UIF GVODUJPO OBNF BOE UIF FRVBMT TJHO XJUI XIJUF TQBDF
5IF OBNF JT B WBSJBCMF BOE XIFO XF BQQMZ UIF GVODUJPO UP
BO BSHVNFOU UIF WBMVF PG UIF BSHVNFOU JT CPVOE PS VOJƶFE
XJUI UIF OBNFE QBSBNFUFS JO PVS GVODUJPO EFƶOJUJPO
'JSTU XFƊMM EFƶOF B WBMVF XJUI OP QBSBNFUFST

myNum :: Integer
myNum = 1

myVal = myNum
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

*G XF RVFSZ UIF UZQF PG myVal

Prelude> :t myVal
myVal :: Integer

5IF WBMVF myVal IBT UIF TBNF UZQF BT myNum CFDBVTF JU JT FRVBM
UP JU 8F DBO TFF GSPN UIF UZQF UIBU JUƊT KVTU B WBMVF XJUIPVU
BOZ QBSBNFUFST TP XF DBOƊU BQQMZ JU UP BOZUIJOH
/PX MFUƊT JOUSPEVDF B QBSBNFUFS OBNFE ԕ

myNum :: Integer
myNum = 1

myVal f = myNum

"OE MFUƊT TFF IPX UIBU DIBOHFE UIF UZQF

Prelude> :t myVal
myVal :: t -> Integer

#Z XSJUJOH ԕ BǒFS myVal XF QBSBNFUFSJ[FE myVal XIJDI DIBOHFT


UIF UZQF GSPN Integer UP t -> Integer 5IF UZQF ԣ JT QPMZNPS
QIJD CFDBVTF XF EPOƊU EP BOZUIJOH XJUI JU ƈ JU DPVME CF BOZ
UIJOH 8F EJEOƊU EP BOZUIJOH XJUI ԕ TP UIF NBYJNBMMZ QPMZ
NPSQIJD UZQF XBT JOGFSSFE *G XF EP TPNFUIJOH XJUI ԕ UIF
UZQF XJMM DIBOHF
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

Prelude> let myNum = 1 :: Integer


Prelude> let myVal f = f + myNum
Prelude> :t myVal
myVal :: Integer -> Integer

/PX JU LOPXT ԕ IBT UP CF PG UZQF Integer CFDBVTF XF BEEFE


JU UP myNum
8F DBO UFMM B TJNQMF WBMVF GSPN B GVODUJPO JO QBSU CFDBVTF
B WBMVF JT OPU BQQMJFE UP BOZ BSHVNFOUT XIJMF GVODUJPOT OFD
FTTBSJMZ IBWF QBSBNFUFST UIBU DBO CF BQQMJFE UP BSHVNFOUT
"MUIPVHI )BTLFMM GVODUJPOT POMZ UBLF POF BSHVNFOU QFS
GVODUJPO XF DBO EFDMBSF NVMUJQMF QBSBNFUFST JO B UFSNMFWFM
GVODUJPO EFƶOJUJPO

myNum :: Num a => a


myNum = 1
-- [1]

myVal :: Num a => a -> a


myVal f = f + myNum
-- [2]

stillAFunction :: [a] -> [a] -> [a] -> [a]


stillAFunction a b c = a ++ b ++ c
-- [ 3 ]
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 %FDMBSBUJPO PG B WBMVF PG UZQF Num a => a 8F DBO UFMM JUƊT


OPU B GVODUJPO CFDBVTF OP QBSBNFUFST BSF OBNFE CFUXFFO
UIF OBNF PG UIF EFDMBSFE WBMVF BOE UIF = TP JU BDDFQUT OP
BSHVNFOUT BOE UIF WBMVF 1 JT OPU B GVODUJPO

 )FSF ԕ JT B OBNF GPS B QBSBNFUFS UP UIF GVODUJPO myVal *U


SFQSFTFOUT UIF QPTTJCJMJUZ PG CFJOH BQQMJFE UP PS CPVOE
UP BO JOQVU WBMVF 5IF GVODUJPO UZQF JT Num a => a -> a
*G ZPV BTTJHO UIF UZQF *OUFHFS UP myNum myNum BOE myVal
NVTU DIBOHF UP UIF UZQFT Integer BOE Integer -> Integer
SFTQFDUJWFMZ

 )FSF Ԑ ԑ BOE Ԓ SFQSFTFOU QBSBNFUFST GPS UIF GVODUJPO


5IF VOEFSMZJOH MPHJD JT PG OFTUFE GVODUJPOT FBDI BQQMJFE
UP POF BSHVNFOU SBUIFS UIBO POF GVODUJPO UBLJOH TFWFSBM
BSHVNFOUT CVU UIJT JT IPX JU BQQFBST BU UFSN MFWFM

/PUJDF XIBU IBQQFOT UP UIF UZQFT BT XF OBNF NPSF QBSBN


FUFST

Prelude> let myVal f g = myNum


Prelude> :t myVal
myVal :: t -> t1 -> Integer

Prelude> let myVal f g h = myNum


Prelude> :t myVal
myVal :: t -> t1 -> t2 -> Integer
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

)FSF UIF UZQFT BSF t t1 BOE t2 XIJDI DPVME CF EJƵFSFOU


UZQFT 5IFZ BSF BMMPXFE CVU OPU SFRVJSFE UP CF EJƵFSFOU UZQFT
5IFZƊSF BMM QPMZNPSQIJD CFDBVTF XF HBWF UIF UZQF JOGFSFODF
OPUIJOH UP HP PO XJUI SFTQFDU UP XIBU UZQF UIFZ DPVME CF 5IF
UZQF WBSJBCMFT BSF EJƵFSFOU CFDBVTF OPUIJOH JO PVS DPEF JT
QSFWFOUJOH UIFN GSPN WBSZJOH TP UIFZ BSF QPUFOUJBMMZ EJG
GFSFOU UZQFT 5IF JOGFSFODF JOGFST UIF NPTU QPMZNPSQIJD UZQF
UIBU XPSLT

#JOEJOH WBSJBCMFT UP WBMVFT


-FUƊT DPOTJEFS IPX UIF CJOEJOH PG WBSJBCMFT XPSLT "QQMZJOH
B GVODUJPO CJOET JUT QBSBNFUFST UP WBMVFT 5ZQF QBSBNFUFST
CFDPNF CPVOE UP B UZQF BOE GVODUJPO WBSJBCMFT BSF CPVOE
UP B WBMVF 5IF CJOEJOH PG WBSJBCMFT DPODFSOT OPU POMZ UIF
BQQMJDBUJPO PG GVODUJPO BSHVNFOUT CVU BMTP UIJOHT MJLF let
FYQSFTTJPOT BOE where DMBVTFT $POTJEFS UIF GPMMPXJOH GVODUJPO

addOne :: Integer -> Integer


addOne x = x + 1

8F EPOƊU LOPX UIF SFTVMU VOUJM UIF addOne GVODUJPO JT BQQMJFE


UP BO Integer WBMVF BSHVNFOU 8IFO addOne JT BQQMJFE UP B
WBMVF XF TBZ UIBU ԧ JT OPX CPVOE UP UIF WBMVF UIF GVODUJPO XBT
BQQMJFE UP 6OUJM B GVODUJPOƊT BSHVNFOUT IBWF CFFO BQQMJFE
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

UIFSFCZ CJOEJOH UIF QBSBNFUFST UP WBMVFT XF DBOOPU NBLF VTF


PG UIF SFTVMU PG UIF GVODUJPO

addOne 1 -- x is now bound to 1


addOne 1 = 1 + 1
= 2

addOne 10 -- x is bound to 10
addOne 10 = 10 + 1
= 11

*O BEEJUJPO UP CJOEJOH WBSJBCMFT UISPVHI GVODUJPO BQQMJDB


UJPO XF DBO VTF let FYQSFTTJPOT UP EFDMBSF BOE CJOE WBSJBCMFT
BT XFMM

bindExp :: Integer -> String


bindExp x = let y = 5 in
"the integer was: " ++ show x
++ " and y was: " ++ show y

*O show y Ԩ JT JO TDPQF CFDBVTF UIF let FYQSFTTJPO CJOET UIF


WBSJBCMF Ԩ UP  Ԩ JT POMZ JO TDPQF JOTJEF UIF let FYQSFTTJPO -FUƊT
TFF TPNFUIJOH UIBU XPOƊU XPSL
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

bindExp :: Integer -> String


bindExp x = let z = y + x in
let y = 5 in "the integer was: "
++ show x ++ " and y was: "
++ show y ++ " and z was: " ++ show z

:PV TIPVME TFF BO FSSPS ƌ/PU JO TDPQF ƉZƊƍ 8F BSF USZJOH


UP NBLF ԩ FRVBM B WBMVF DPOTUSVDUFE GSPN ԧ BOE Ԩ ԧ JT JO
TDPQF CFDBVTF UIF GVODUJPO BSHVNFOU JT WJTJCMF BOZXIFSF JO
UIF GVODUJPO )PXFWFS Ԩ JT CPVOE JO UIF FYQSFTTJPO UIBU let z
= … XSBQT TP JUƊT OPU JO TDPQF ZFU ƈ UIBU JT JUƊT OPU WJTJCMF UP
UIF NBJO GVODUJPO
*O TPNF DBTFT GVODUJPO BSHVNFOUT BSF OPU WJTJCMF JO UIF
GVODUJPO JG UIFZ IBWF CFFO TIBEPXFE -FUƊT MPPL BU B DBTF PG
TIBEPXJOH

bindExp :: Integer -> String


bindExp x = let x = 10; y = 5 in
"the integer was: " ++ show x
++ " and y was: " ++ show y

*G ZPV BQQMZ UIJT UP BO BSHVNFOU ZPVƊMM OPUJDF UIF SFTVMU


OFWFS DIBOHFT

Prelude> bindExp 9001


"the integer was: 10 and y was: 5"
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

5IJT JT CFDBVTF UIF SFGFSFODF UP ԧ BSJTJOH GSPN UIF BSHVNFOU


ԧ XBT TIBEPXFE CZ UIF ԧ GSPN UIF let CJOEJOH 5IF EFƶOJUJPO
PG ԧ UIBU JT JOOFSNPTU JO UIF DPEF XIFSF UIF GVODUJPO OBNF BU
UIF MFǒ NBSHJO JT UIF PVUTJEF
UBLFT QSFDFEFODF CFDBVTF )BTLFMM
JT MFYJDBMMZ TDPQFE -FYJDBM TDPQJOH NFBOT UIBU SFTPMWJOH UIF
WBMVF GPS B OBNFE FOUJUZ EFQFOET PO UIF MPDBUJPO JO UIF DPEF
BOE UIF MFYJDBM DPOUFYU GPS FYBNQMF JO let BOE where DMBVTFT
"NPOH PUIFS UIJOHT UIJT NBLFT JU FBTJFS UP LOPX XIBU WBMVFT
SFGFSSFE UP CZ OBNF BSF BOE XIFSF UIFZ DPNF GSPN -FUƊT
BOOPUBUF UIF QSFWJPVT FYBNQMF BOE XFƊMM TFF XIBU JT NFBOU
IFSF

bindExp :: Integer -> String


bindExp x = let x = 10; y = 5 in "x: " ++ show x
-- [1] [2] [3]
++ " y: " ++ show y

 5IF QBSBNFUFS ԧ JOUSPEVDFE JO UIF EFƶOJUJPO PG bindExp


5IJT HFUT TIBEPXFE CZ UIF ԧ JO [2]

 5IJT JT B letCJOEJOH PG ԧ BOE TIBEPXT UIF EFƶOJUJPO PG ԧ


JOUSPEVDFE BT BO BSHVNFOU BU [1]

 " VTF PG UIF ԧ CPVOE CZ [2] (JWFO )BTLFMMƊT TUBUJD MFYJDBM

TDPQJOH JU XJMM BMXBZT SFGFS UP UIF ԧ EFƶOFE BT x = 10 JO UIF


let CJOEJOH
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

:PV DBO BMTP TFF UIF FƵFDU PG TIBEPXJOH B OBNF JO TDPQF JO


()$J VTJOH UIF let TUBUFNFOUT ZPVƊWF CFFO LJDLJOH BSPVOE BMM
BMPOH

Prelude> let x = 5
Prelude> let y = x + 5
Prelude> y
10
Prelude> y * 10
100
Prelude> let z y = y * 10
Prelude> x
5
Prelude> y
10
Prelude> z 9
90

-- but
Prelude> z y
100

/PUF UIBU XIJMF Ԩ JT CPVOE JO ()$JƊT TDPQF UP x + 5 UIF


JOUSPEVDUJPO PG z y = y * 10 DSFBUFT B OFX JOOFS TDPQF XIJDI
TIBEPXFE UIF OBNF Ԩ /PX XIFO XF DBMM ԩ ()$J XJMM VTF UIF
WBMVF XF QBTT BT Ԩ UP FWBMVBUF UIF FYQSFTTJPO OPU OFDFTTBSJMZ
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

UIF WBMVF 10 GSPN UIF let TUBUFNFOU y = x + 5 6TJOH Ԩ BT BO


BSHVNFOU UP ԩ BT JO UIF MBTU FYBNQMF NFBOT UIF WBMVF PG Ԩ
GSPN UIF PVUFS TDPQF JT QBTTFE UP ԩ BT BO BSHVNFOU 5IF MFY
JDBMMZ JOOFSNPTU CJOEJOH GPS B WBSJBCMF PG B QBSUJDVMBS OBNF
BMXBZT UBLFT QSFDFEFODF *U EPFT OPU NBUUFS UIBU UIF Ԩ JO ԩƊT
QBSBNFUFST IBT UIF TBNF OBNF BT UIF Ԩ GSPN FBSMJFS JO ()$J
Ԩ XJMM BMXBZT CF CPVOE UP UIF WBMVF UIBU ԩ JT BQQMJFE UP *ODJ
EFOUBMMZ UIF TFFNJOHTFRVFOUJBMJUZ PG EFƶOJOH UIJOHT JO ()$J
JT VOEFS UIF IPPE BDUVBMMZ B OFWFSFOEJOH TFSJFT PG OFTUFE
MBNCEB FYQSFTTJPOT TJNJMBS UP UIF XBZ GVODUJPOT DBO TFFN UP
BDDFQU NVMUJQMF BSHVNFOUT CVU BSF BU SPPU B TFSJFT PG OFTUFE
GVODUJPOT


 "OPOZNPVT GVODUJPOT


8F IBWF BMSFBEZ TFFO IPX UP XSJUF BOPOZNPVT GVODUJPOT VTJOH
UIF MBNCEB TZOUBY SFQSFTFOUFE CZ B CBDLTMBTI "OPOZNPVT
NFBOT ƌXJUIPVU B OBNFƍ BOE UIBU HJWFT VT B DMVF UP XIZ XF IBWF
UIJT TZOUBY ƈ UP DPOTUSVDU GVODUJPOT BOE VTF UIFN XJUIPVU
HJWJOH UIFN B OBNF
'PS FYBNQMF FBSMJFS XF MPPLFE BU UIJT OBNFE JF OPU BOPOZ
NPVT GVODUJPO

triple :: Integer -> Integer


triple x = x * 3
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

"OE IFSF JT UIF TBNF GVODUJPO CVU XJUI BOPOZNPVT GVODUJPO


TZOUBY

(\x -> x * 3) :: Integer -> Integer

:PV OFFE UIF QBSFOUIFTFT GPS UIF UZQF BTTFSUJPO :: Integer


-> Integer UP BQQMZ UP UIF FOUJSF BOPOZNPVT GVODUJPO BOE OPU
KVTU UIF Num a => a WBMVF  :PV DBO HJWF UIJT GVODUJPO B OBNF
NBLJOH JU OPU BOPOZNPVT BOZNPSF JO ()$J MJLF UIJT

Prelude> let trip = (\x -> x*3) :: Integer -> Integer

4JNJMBSMZ UP BQQMZ BO BOPOZNPVT GVODUJPO XFƊMM PǒFO OFFE


UP XSBQ JU JO QBSFOUIFTFT TP UIBU PVS JOUFOU JT DMFBS

Prelude> (\x -> x * 3) 5


15
Prelude> \x -> x * 3 1

Could not deduce (Num (a0 -> a))


arising from the ambiguity check for ‘it’
from the context (Num (a1 -> a), Num a1, Num a)
bound by the inferred type for ‘it’:
(Num (a1 -> a), Num a1, Num a) => a -> a
at <interactive>:9:1-13
The type variable ‘a0’ is ambiguous
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

When checking that ‘it’


has the inferred type ‘forall a a1.
(Num (a1 -> a), Num a1, Num a) =>
a -> a’
Probable cause: the inferred type is ambiguous

5IF UZQF FSSPS Could not deduce (Num (a0 -> a)) JT CFDBVTF
ZPV DBOƊU VTF Num a => a WBMVFT BT JG UIFZ XFSF GVODUJPOT 5P
UIF DPNQVUFS JU MPPLT MJLF ZPVƊSF USZJOH UP VTF  BT B GVODUJPO
BOE BQQMZ  UP  )FSF UIF it SFGFSSFE UP JT 3 1 XIJDI JU UIJOLT
JT 3 BQQMJFE UP 1 BT JG 3 XFSF B GVODUJPO

&YFSDJTFT (SBC #BH


/PUF UIF GPMMPXJOH FYFSDJTFT BSF GSPN TPVSDF DPEF ƶMFT OPU
XSJUUFO GPS VTF EJSFDUMZ JO UIF 3&1- 0G DPVSTF ZPV DBO DIBOHF
UIFN UP UFTU EJSFDUMZ JO UIF 3&1- JG ZPV QSFGFS

 8IJDI UXP PS NPSF


PG UIF GPMMPXJOH BSF FRVJWBMFOU

B
mTh x y z = x * y * z

C
mTh x y = \z -> x * y * z

D
mTh x = \y -> \z -> x * y * z

E
mTh = \x -> \y -> \z -> x * y * z

*O ()$J FSSPS NFTTBHFT it SFGFST UP UIF MBTU FYQSFTTJPO ZPV FOUFSFE
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 5IF UZQF PG mTh BCPWF


JT Num a => a -> a -> a -> a
8IJDI JT UIF UZQF PG mTh 3

B
Integer -> Integer -> Integer
C
Num a => a -> a -> a -> a
D
Num a => a -> a
E
Num a => a -> a -> a

 /FYU XFƊMM QSBDUJDF XSJUJOH BOPOZNPVT MBNCEB TZOUBY


'PS FYBNQMF POF DPVME SFXSJUF

addOne x = x + 1

*OUP

addOne = \x -> x + 1

5SZ UP NBLF JU TP JU DBO TUJMM CF MPBEFE BT B UPQMFWFM EFG


JOJUJPO CZ ()$J 5IJT XJMM NBLF JU FBTJFS UP WBMJEBUF ZPVS
BOTXFST

B
3FXSJUF UIF f GVODUJPO JO UIF XIFSF DMBVTF

addOneIfOdd n = case odd n of


True -> f n
False -> n
where f n = n + 1
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

C
3FXSJUF UIF GPMMPXJOH UP VTF BOPOZNPVT MBNCEB TZO
UBY

addFive x y = (if x > y then y else x) + 5


D
3FXSJUF UIF GPMMPXJOH TP UIBU JU EPFTOƊU VTF BOPOZ
NPVT MBNCEB TZOUBY

mflip f = \x -> \y -> f y x

5IF VUJMJUZ PG MBNCEB TZOUBY


:PVƊSF HPJOH UP TFF UIJT BOPOZNPVT TZOUBY B MPU BT XF QSPDFFE
UISPVHI UIF CPPL CVU SJHIU OPX JU NBZ OPU TFFN UP CF UIBU
VTFGVM ƈ JUƊT KVTU BOPUIFS XBZ UP XSJUF GVODUJPOT BǒFS BMM
:PV NPTU PǒFO VTF UIJT TZOUBY XIFO ZPVƊSF QBTTJOH B GVOD
UJPO JO BT BO BSHVNFOU UP B IJHIFSPSEFS GVODUJPO NPSF PO
UIJT TPPO
BOE UIBUƊT UIF POMZ QMBDF JO ZPVS QSPHSBN XIFSF
UIBU QBSUJDVMBS GVODUJPO XJMM CF VTFE *G ZPVƊSF OFWFS HPJOH UP
DBMM JU CZ OBNF UIFO JU EPFTOƊU OFFE UP CF HJWFO B OBNF
8F XPOƊU HP JOUP B MPU PG EFUBJM BCPVU UIJT ZFU CVU OBNFE
FOUJUJFT BOE BOPOZNPVT FOUJUJFT FWBMVBUF B CJU EJƵFSFOUMZ JO
)BTLFMM BOE UIBU DBO CF POF SFBTPO UP VTF BO BOPOZNPVT
GVODUJPO JO TPNF DBTFT
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 1BUUFSO NBUDIJOH


1BUUFSO NBUDIJOH JT BO JOUFHSBM BOE VCJRVJUPVT GFBUVSF PG
)BTLFMM 4P JOUFHSBM BOE VCJRVJUPVT UIBU XFƊWF CFFO VTJOH
JU UISPVHIPVU UIF CPPL XJUIPVU TBZJOH BOZUIJOH BCPVU JU 0ODF
ZPV TUBSU ZPV DBOƊU TUPQ
1BUUFSO NBUDIJOH JT B XBZ PG NBUDIJOH WBMVFT BHBJOTU QBU
UFSOT BOE XIFSF BQQSPQSJBUF CJOEJOH WBSJBCMFT UP TVDDFTTGVM
NBUDIFT *U JT XPSUI OPUJOH IFSF UIBU QBUUFSOT DBO JODMVEF UIJOHT
BT EJWFSTF BT VOEFƶOFE WBSJBCMFT OVNFSJD MJUFSBMT BOE MJTU TZO
UBY "T XF XJMM TFF QBUUFSO NBUDIJOH NBUDIFT PO BOZ BOE BMM
EBUB DPOTUSVDUPST
1BUUFSO NBUDIJOH BMMPXT ZPV UP FYQPTF EBUB BOE EJTQBUDI
EJƵFSFOU CFIBWJPST CBTFE PO UIBU EBUB JO ZPVS GVODUJPO EFƶOJ
UJPOT CZ EFDPOTUSVDUJOH WBMVFT UP FYQPTF UIFJS JOOFS XPSLJOHT
5IFSF JT B SFBTPO XF EFTDSJCF WBMVFT BT ƌEBUB DPOTUSVDUPSTƍ BM
UIPVHI XF IBWFOƊU FYQMPSFE UIBU NVDI ZFU 1BUUFSO NBUDIJOH
BMTP BMMPXT VT UP XSJUF GVODUJPOT UIBU DBO EFDJEF CFUXFFO UXP
PS NPSF QPTTJCJMJUJFT CBTFE PO XIJDI WBMVF JU NBUDIFT
1BUUFSOT BSF NBUDIFE BHBJOTU WBMVFT PS EBUB DPOTUSVDUPST
OPU UZQFT .BUDIJOH B QBUUFSO NBZ GBJM QSPDFFEJOH UP UIF OFYU
BWBJMBCMF QBUUFSO UP NBUDI PS TVDDFFE 8IFO B NBUDI TVD
DFFET UIF WBSJBCMFT FYQPTFE JO UIF QBUUFSO BSF CPVOE 1BUUFSO
NBUDIJOH QSPDFFET GSPN MFǒ UP SJHIU BOE PVUTJEF UP JOTJEF
8F DBO QBUUFSO NBUDI PO OVNCFST *O UIF GPMMPXJOH FYBN
QMF XIFO UIF Integer BSHVNFOU UP UIF GVODUJPO FRVBMT  UIJT
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

SFUVSOT True PUIFSXJTF False

isItTwo :: Integer -> Bool


isItTwo 2 = True
isItTwo _ = False

:PV DBO FOUFS UIF TBNF GVODUJPO EJSFDUMZ JOUP ()$J VTJOH
UIF :{ BOE :} CMPDL TZOUBY KVTU FOUFS :} BOE ƌSFUVSOƍ UP FOE
UIF CMPDL

Prelude> :{
*Main| let isItTwo :: Integer -> Bool
*Main| isItTwo 2 = True
*Main| isItTwo _ = False
*Main| :}

/PUF UIF VTF PG UIF VOEFSTDPSF _ BǒFS UIF NBUDI BHBJOTU UIF
WBMVF 2 5IJT JT B NFBOT PG EFƶOJOH B VOJWFSTBM QBUUFSO UIBU
OFWFS GBJMT UP NBUDI B TPSU PG ƌBOZUIJOH FMTFƍ DBTF

Prelude> isItTwo 2
True
Prelude> isItTwo 3
False

)BOEMJOH BMM UIF DBTFT


5IF PSEFS PG QBUUFSO NBUDIFT NBUUFST 5IF GPMMPXJOH WFSTJPO
PG UIF GVODUJPO XJMM BMXBZT SFUVSO False CFDBVTF JU XJMM NBUDI
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

UIF ƌBOZUIJOH FMTFƍ DBTF ƶSTU ƈ BOE NBUDI JU UP FWFSZUIJOH ƈ


TP OPUIJOH XJMM HFU UISPVHI UIBU UP NBUDI XJUI UIF QBUUFSO ZPV
EP XBOU UP NBUDI

isItTwo :: Integer -> Bool


isItTwo _ = False
isItTwo 2 = True

<interactive>:9:33: Warning:
Pattern match(es) are overlapped
In an equation for ‘isItTwo’: isItTwo 2 = ...
Prelude> isItTwo 2
False
Prelude> isItTwo 3
False

5SZ UP PSEFS ZPVS QBUUFSOT GSPN NPTU TQFDJƶD UP MFBTU TQF


DJƶD QBSUJDVMBSMZ BT JU DPODFSOT UIF VTF PG _ UP VODPOEJUJPOBMMZ
NBUDI BOZ WBMVF 6OMFTT ZPV HFU GBODZ ZPV TIPVME CF BCMF
UP USVTU ()$ƊT QBUUFSO NBUDI PWFSMBQ XBSOJOH BOE TIPVME
USJQMFDIFDL ZPVS DPEF XIFO JU DPNQMBJOT
8IBU IBQQFOT JG XF GPSHFU UP NBUDI B DBTF JO PVS QBUUFSO

isItTwo :: Integer -> Bool


isItTwo 2 = True

/PUJDF UIBU OPX PVS GVODUJPO DBO POMZ QBUUFSO NBUDI PO UIF
WBMVF  5IJT JT BO JODPNQMFUF QBUUFSO NBUDI CFDBVTF JU DBOƊU
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

NBUDI BOZ PUIFS EBUB *ODPNQMFUF QBUUFSO NBUDIFT BQQMJFE UP


EBUB UIFZ EPOƊU IBOEMF XJMM SFUVSO CPUUPN B OPOWBMVF VTFE UP
EFOPUF UIBU UIF QSPHSBN DBOOPU SFUVSO B WBMVF PS SFTVMU 5IJT
XJMM UISPX BO FYDFQUJPO XIJDI JG VOIBOEMFE XJMM NBLF ZPVS
QSPHSBN GBJM

Prelude> isItTwo 2
True
Prelude> isItTwo 3
*** Exception: :50:33-48:
Non-exhaustive patterns
in function isItTwo

8FƊSF HPJOH UP HFU XFMM BDRVBJOUFE XJUI UIF JEFB PG CPUUPN


JO VQDPNJOH DIBQUFST 'PS OPX JUƊT FOPVHI UP LOPX UIBU UIJT
JT XIBU ZPV HFU XIFO ZPV EPOƊU IBOEMF BMM UIF QPTTJCMF EBUB
'PSUVOBUFMZ UIFSFƊT B XBZ UP LOPX BU DPNQJMF UJNF XIFO
ZPVS QBUUFSO NBUDIFT BSF OPOFYIBVTUJWF BOE EPOƊU IBOEMF
FWFSZ DBTF

Prelude> :set -Wall


Prelude> :{
*Main| let isItTwo :: Integer -> Bool
*Main| isItTwo 2 = True
*Main| :}

<interactive>:28:5: Warning:
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

This binding for ‘isItTwo’ shadows


the existing binding
defined at <interactive>:20:5

<interactive>:28:5: Warning:
Pattern match(es) are non-exhaustive
In an equation for ‘isItTwo’:

Patterns not matched: #x with #x `notElem` [2#]

#Z UVSOJOH PO BMM XBSOJOHT XJUI -Wall XFƊSF OPX UPME BIFBE


PG UJNF UIBU XFƊWF NBEF B NJTUBLF %P OPU JHOPSF UIF XBSOJOHT
()$ QSPWJEFT GPS ZPV

1BUUFSO NBUDIJOH BHBJOTU EBUB DPOTUSVDUPST


1BUUFSO NBUDIJOH TFSWFT B DPVQMF PG QVSQPTFT *U FOBCMFT VT UP
WBSZ XIBU PVS GVODUJPOT EP HJWFO EJƵFSFOU JOQVUT *U BMTP BMMPXT
VT UP VOQBDL BOE FYQPTF UIF DPOUFOUT PG PVS EBUB 5IF WBMVFT
True BOE False EPOƊU IBWF BOZ PUIFS EBUB UP FYQPTF CVU TPNF
EBUB DPOTUSVDUPST IBWF QBSBNFUFST BOE QBUUFSO NBUDIJOH DBO
MFU VT FYQPTF BOE NBLF VTF PG UIF EBUB JO UIFJS BSHVNFOUT
5IF OFYU FYBNQMF VTFT newtype XIJDI JT B TQFDJBM DBTF PG data
EFDMBSBUJPOT newtype JT EJƵFSFOU JO UIBU JU QFSNJUT POMZ POF
DPOTUSVDUPS BOE POMZ POF ƶFME 8F XJMM UBML BCPVU newtype NPSF
MBUFS 'PS OPX XF XBOU UP GPDVT PO IPX QBUUFSO NBUDIJOH DBO
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

CF VTFE UP FYQPTF UIF DPOUFOUT PG EBUB BOE TQFDJGZ CFIBWJPS


CBTFE PO UIBU EBUB

-- registeredUser1.hs
module RegisteredUser where

newtype Username = Username String


newtype AccountNumber = AccountNumber Integer

data User = UnregisteredUser


| RegisteredUser Username AccountNumber

8JUI UIF UZQF User XF DBO VTF QBUUFSO NBUDIJOH UP BD


DPNQMJTI UXP UIJOHT 'JSTU User JT B TVN XJUI UXP DPOTUSVD
UPST UnregisteredUser BOE RegisteredUser 8F DBO VTF QBUUFSO
NBUDIJOH UP EJTQBUDI PVS GVODUJPO EJƵFSFOUMZ EFQFOEJOH PO
XIJDI WBMVF XF HFU 5IFO XJUI UIF RegisteredUser DPOTUSVD
UPS XF TFF UIBU JU JT B QSPEVDU PG UXP newtypeT Username BOE
AccountNumber 8F DBO VTF QBUUFSO NBUDIJOH UP CSFBL EPXO
OPU POMZ RegisteredUserƊT DPOUFOUT CVU BMTP UIBU PG UIF newtypes
JG BMM UIF DPOTUSVDUPST BSF JO TDPQF -FUƊT XSJUF B GVODUJPO UP
QSFUUZQSJOU User WBMVFT
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

-- registeredUser2.hs
module RegisteredUser where

newtype Username = Username String


newtype AccountNumber = AccountNumber Integer

data User = UnregisteredUser


| RegisteredUser Username AccountNumber

printUser :: User -> IO ()


printUser UnregisteredUser = putStrLn "UnregisteredUser"
printUser (RegisteredUser (Username name)
(AccountNumber acctNum))
= putStrLn $ name ++ " " ++ show acctNum

/PUF UIBU ZPV DBO DPOUJOVF UIF QBUUFSO PO UIF OFYU MJOF JG JU
HFUT UPP MPOH /FYU MFUƊT MPBE UIJT JOUP UIF 3&1- BOE MPPL BU
UIF UZQFT

Prelude> :l code/registeredUser2.hs
...
Prelude> :t RegisteredUser
RegisteredUser :: Username -> AccountNumber -> User
Prelude> :t Username
Username :: String -> Username
Prelude> :t AccountNumber
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

AccountNumber :: Integer -> AccountNumber

/PUJDF IPX UIF UZQF PG RegisteredUser JT B GVODUJPO UIBU DPO


TUSVDUT B User PVU PG UXP BSHVNFOUT Username BOE AccountNumber
5IJT JT XIBU XF NFBO XIFO XF SFGFS UP B WBMVF BT B ƌEBUB DPO
TUSVDUPSƍ
/PX MFUƊT VTF PVS GVODUJPOT 5IF BSHVNFOU OBNFT BSF UF
EJPVT UP UZQF JO CVU UIFZ XFSF DIPTFO UP FOTVSF DMBSJUZ 1BTTJOH
UIF GVODUJPO BO UnregisteredUser SFUVSOT UIF FYQFDUFE WBMVF

Prelude> printUser UnregisteredUser


UnregisteredUser

5IF GPMMPXJOH UIPVHI BTLT JU UP NBUDI PO EBUB DPOTUSVDUPS


RegisteredUser BOE BMMPXT VT UP DPOTUSVDU B User PVU PG UIF 4USJOH
ƌDBMMFOƍ BOE UIF Integer 

Prelude> let myUser = (Username "callen")


Prelude> let myAcct = (AccountNumber 10456)
Prelude> printUser $ RegisteredUser myUser myAcct
callen 10456

5ISPVHI UIF VTF PG QBUUFSO NBUDIJOH XF XFSF BCMF UP VO


QBDL UIF RegisteredUser WBMVF PG UIF User UZQF BOE WBSZ CFIBW
JPS PWFS UIF EJƵFSFOU DPOTUSVDUPST PG UZQFT
5IJT JEFB PG VOQBDLJOH BOE EJTQBUDIJOH PO EBUB JT JNQPS
UBOU TP MFU VT FYBNJOF BOPUIFS FYBNQMF 'JSTU XFƊSF HPJOH UP
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

XSJUF B DPVQMF PG OFX EBUBUZQFT 8SJUJOH ZPVS PXO EBUBUZQFT


XPOƊU CF GVMMZ FYQMBJOFE VOUJM B MBUFS DIBQUFS CVU NPTU PG UIF
TUSVDUVSF IFSF TIPVME CF GBNJMJBS BMSFBEZ 8F IBWF B TVN UZQF
DBMMFE WherePenguinsLive

data WherePenguinsLive =
Galapagos
| Antarctica
| Australia
| SouthAfrica
| SouthAmerica
deriving (Eq, Show)

"OE B QSPEVDU UZQF DBMMFE Penguin. 8F IBWFOƊU HJWFO QSPE


VDU UZQFT NVDI BUUFOUJPO ZFU CVU GPS OPX ZPV DBO UIJOL PG
Penguin BT B UZQF XJUI POMZ POF WBMVF Peng BOE UIBU WBMVF JT B
TPSU PG CPY UIBU DPOUBJOT B WherePenguinsLive WBMVF

data Penguin =
Peng WherePenguinsLive
deriving (Eq, Show)

(JWFO UIFTF EBUBUZQFT XF XJMM XSJUF B DPVQMF GVODUJPOT GPS


QSPDFTTJOH UIF EBUB
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

-- is it South Africa? If so, return True


isSouthAfrica :: WherePenguinsLive -> Bool
isSouthAfrica SouthAfrica = True
isSouthAfrica Galapagos = False
isSouthAfrica Antarctica = False
isSouthAfrica Australia = False
isSouthAfrica SouthAmerica = False

#VU UIBU JT SFEVOEBOU 8F DBO VTF _ UP JOEJDBUF BO VODPOEJ


UJPOBM NBUDI PO B WBMVF XF EPOƊU DBSF BCPVU 5IF GPMMPXJOH JT
CFUUFS NPSF DPODJTF FBTJFS UP SFBE
BOE EPFT UIF TBNF UIJOH

isSouthAfrica' :: WherePenguinsLive -> Bool


isSouthAfrica' SouthAfrica = True
isSouthAfrica' _ = False

8F DBO BMTP VTF QBUUFSO NBUDIJOH UP VOQBDL Penguin WBMVFT


UP HFU BU UIF WherePenguinsLive WBMVF JU DPOUBJOT

gimmeWhereTheyLive :: Penguin -> WherePenguinsLive


gimmeWhereTheyLive (Peng whereitlives) = whereitlives

5SZ VTJOH UIF gimmeWhereTheyLive GVODUJPO PO TPNF UFTU EBUB


8IFO ZPV FOUFS UIF OBNF PG UIF QFOHVJO OPUF UIF MPXFSDBTF

JU XJMM VOQBDL UIF Peng WBMVF UP KVTU SFUVSO UIF WherePenguinsLive
UIBUƊT JOTJEF
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

humboldt = Peng SouthAmerica


gentoo = Peng Antarctica
macaroni = Peng Antarctica
little = Peng Australia
galapagos = Peng Galapagos

/PX B NPSF FMBCPSBUF FYBNQMF 8FƊMM FYQPTF UIF DPOUFOUT


PG Peng BOE NBUDI PO XIBU WherePenguinLives WBMVF XF DBSF
BCPVU JO POF QBUUFSO NBUDI

galapagosPenguin :: Penguin -> Bool


galapagosPenguin (Peng Galapagos) = True
galapagosPenguin _ = False

antarcticPenguin :: Penguin -> Bool


antarcticPenguin (Peng Antarctica) = True
antarcticPenguin _ = False

-- in this final function, the || operator


-- is an `or` function, which will return True
-- if either value is True
antarcticOrGalapagos :: Penguin -> Bool
antarcticOrGalapagos p =
(galapagosPenguin p) || (antarcticPenguin p)

/PUF UIBU XFƊSF VTJOH QBUUFSO NBUDIJOH UP BDDPNQMJTI UXP


$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

UIJOHT IFSF 8FƊSF VTJOH JU UP VOQBDL UIF Penguin EBUBUZQF


8FƊSF BMTP TQFDJGZJOH XIJDI WherePenguinsLive WBMVF XF XBOU
UP NBUDI PO

1BUUFSO NBUDIJOH UVQMFT


:PV DBO BMTP VTF QBUUFSO NBUDIJOH SBUIFS UIBO GVODUJPOT GPS
PQFSBUJOH PO UIF DPOUFOUT PG UVQMFT 3FNFNCFS UIJT FYBNQMF
GSPN #BTJD %BUBUZQFT

f :: (a, b) -> (c, d) -> ((b, d), (a, c))


f = undefined

8IFO ZPV EJE UIBU FYFSDJTF ZPV NBZ IBWF XSJUUFO JU MJLF
UIJT

f :: (a, b) -> (c, d) -> ((b, d), (a, c))


f x y = ((snd x, snd y), (fst x, fst y))

#VU XF DBO VTF QBUUFSO NBUDIJOH PO UVQMFT UP NBLF B DMFBSFS


BOE OJDFS UP SFBE WFSTJPO PG JU

f :: (a, b) -> (c, d) -> ((b, d), (a, c))


f (a, b) (c, d) = ((b, d), (a, c))

0OF OJDF UIJOH BCPVU UIJT JT UIBU UIF UVQMF TZOUBY BMMPXT UIF
GVODUJPO UP MPPL B HSFBU EFBM MJLF JUT UZQF -FUƊT MPPL BU NPSF
FYBNQMFT PG QBUUFSO NBUDIJOH PO UVQMFT /PUF UIBU UIF TFDPOE
FYBNQMF CFMPX JT OPU B QBUUFSO NBUDI CVU UIF PUIFST BSF
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

-- matchingTuples1.hs
module TupleFunctions where

-- These have to be the same type because


-- (+) is a -> a -> a
addEmUp2 :: Num a => (a, a) -> a
addEmUp2 (x, y) = x + y

-- addEmUp2 could also be written like so


addEmUp2Alt :: Num a => (a, a) -> a
addEmUp2Alt tup = (fst tup) + (snd tup)

fst3 :: (a, b, c) -> a


fst3 (x, _, _) = x

third3 :: (a, b, c) -> c


third3 (_, _, x) = x

Prelude> :l code/matchingTuples1.hs
[1 of 1] Compiling TupleFunctions
Ok, modules loaded: TupleFunctions.

/PX XFƊSF HPJOH UP VTF ()$JƊT :browse UP TFF B MJTU PG UIF


UZQF TJHOBUVSFT BOE GVODUJPOT XF MPBEFE GSPN UIF NPEVMF
TupleFunctions
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

Prelude> :browse TupleFunctions


addEmUp2 :: Num a => (a, a) -> a
addEmUp2Alt :: Num a => (a, a) -> a
fst3 :: (a, b, c) -> a
third3 :: (a, b, c) -> c

Prelude> addEmUp2 (10, 20)


30
Prelude> addEmUp2Alt (10, 20)
30
Prelude> fst3 ("blah", 2, [])
"blah"
Prelude> third3 ("blah", 2, [])
[]

4XFFU -FUƊT EP TPNF FYFSDJTFT 1BVTJOH UP FYFSDJTF LFFQT


UIF NVTDMFT ƷFYJCMF FWFO UIF NFOUBM POFT

&YFSDJTFT 7BSJFUZ 1BDL


 (JWFO UIF GPMMPXJOH EFDMBSBUJPOT

k (x, y) = x
k1 = k ((4-1), 10)
k2 = k ("three", (1 + 2))
k3 = k (3, True)
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

B
8IBU JT UIF UZQF PG k
C
8IBU JT UIF UZQF PG k2 *T JU UIF TBNF UZQF BT k1 PS k3
D
0G k1, k2, k3 XIJDI XJMM SFUVSO UIF OVNCFS  BT UIF
SFTVMU

 'JMM JO UIF EFƶOJUJPO PG UIF GPMMPXJOH GVODUJPO

-- Remember: Tuples have the same syntax for their


-- type constructors and their data constructors.

f :: (a, b, c) -> (d, e, f) -> ((a, d), (c, f))


f = undefined

 $BTF FYQSFTTJPOT


$BTF FYQSFTTJPOT BSF B XBZ TJNJMBS JO TPNF SFTQFDUT UP if-then-else
PG NBLJOH B GVODUJPO SFUVSO B EJƵFSFOU SFTVMU CBTFE PO EJƵFS
FOU JOQVUT :PV DBO VTF DBTF FYQSFTTJPOT XJUI BOZ EBUBUZQF UIBU
IBT WJTJCMF EBUB DPOTUSVDUPST 8IFO XF DPOTJEFS UIF EBUBUZQF
Bool

data Bool = False | True


-- [1] [2] [3]

 5ZQF DPOTUSVDUPS XF POMZ VTF UIJT JO UZQF TJHOBUVSFT OPU


JO UFSNMFWFM DPEF MJLF DBTF FYQSFTTJPOT
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 %BUB DPOTUSVDUPS GPS UIF JOIBCJUBOU PG Bool OBNFE False


ƈ XF DBO NBUDI PO UIJT

 %BUB DPOTUSVDUPS GPS UIF JOIBCJUBOU PG Bool OBNFE True ƈ


XF DBO NBUDI PO UIJT BT XFMM

"OZ UJNF XF DBTF NBUDI PS QBUUFSO NBUDI PO B TVN UZQF


MJLF Bool XF TIPVME EFƶOF IPX XF IBOEMF FBDI DPOTUSVDUPS
PS QSPWJEF B EFGBVMU UIBU NBUDIFT BMM PG UIFN *O GBDU XF NVTU
IBOEMF CPUI DBTFT PS VTF B GVODUJPO UIBU IBOEMFT CPUI PS XF
XJMM IBWF XSJUUFO B QBSUJBM GVODUJPO UIBU DBO UISPX BO FSSPS
BU SVOUJNF 5IFSF JT SBSFMZ B HPPE SFBTPO UP EP UIJT XSJUF
GVODUJPOT UIBU IBOEMF BMM JOQVUT QPTTJCMF
-FUƊT TUBSU CZ MPPLJOH BU BO if-then-else FYQSFTTJPO UIBU XF
TBX JO B QSFWJPVT DIBQUFS

if x + 1 == 1 then "AWESOME" else "wut"

8F DBO SFXSJUF UIJT BT B DBTF FYQSFTTJPO NBUDIJOH PO UIF


DPOTUSVDUPST PG Bool

funcZ x =
case x + 1 == 1 of
True -> "AWESOME"
False -> "wut"
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

/PUF UIBU XIJMF UIF TZOUBY JT DPOTJEFSBCMZ EJƵFSFOU IFSF


UIF SFTVMUT XJMM CF UIF TBNF #F TVSF UP MPBE JU JO UIF 3&1- BOE
USZ JU PVU
8F DPVME BMTP XSJUF B DBTF FYQSFTTJPO UP UFMM VT XIFUIFS PS
OPU TPNFUIJOH JT B QBMJOESPNF

pal xs =
case xs == reverse xs of
True -> "yes"
False -> "no"

5IF BCPWF DBO BMTP CF XSJUUFO XJUI B where DMBVTF JO DBTFT


XIFSF ZPV NJHIU OFFE UP SFVTF UIF Ԩ

pal' xs =
case y of
True -> "yes"
False -> "no"
where y = xs == reverse xs

*O FJUIFS DBTF UIF GVODUJPO XJMM ƶSTU DIFDL JG UIF JOQVU TUSJOH
JT FRVBM UP UIF SFWFSTF PG JU *G UIBU SFUVSOT True UIFO UIF TUSJOH
JT B QBMJOESPNF TP ZPVS GVODUJPO TBZT ƌZFTƍ *G OPU UIFO JUƊT
OPU
)FSF JT POF NPSF FYBNQMF BMTP NBUDIJOH PO UIF EBUB DPO
TUSVDUPST GSPN Bool BOE ZPV DBO DPNQBSF JUT TZOUBY UP UIF
if-then-else WFSTJPO XFƊWF TFFO CFGPSF
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

-- greetIfCool3.hs
module GreetIfCool3 where

greetIfCool :: String -> IO ()


greetIfCool coolness =
case cool of
True -> putStrLn "eyyyyy. What's shakin'?"
False -> putStrLn "pshhhh."
where cool = coolness == "downright frosty yo"

4P GBS UIF DBTF FYQSFTTJPOT XFƊWF MPPLFE BU SFMZ PO B TUSBJHIU


GPSXBSE QBUUFSO NBUDI XJUI True BOE False FYQMJDJUMZ *O BO
VQDPNJOH TFDUJPO XFƊMM MPPL BU BOPUIFS XBZ UP XSJUF B DBTF
FYQSFTTJPO

&YFSDJTFT $BTF 1SBDUJDF


8FƊSF HPJOH UP QSBDUJDF VTJOH DBTF FYQSFTTJPOT CZ SFXSJUJOH
GVODUJPOT 4PNF PG UIFTF GVODUJPOT ZPVƊWF TFFO JO QSFWJPVT
DIBQUFST BOE TPNF ZPVƊMM TFF MBUFS VTJOH EJƵFSFOU TZOUBY ZFU
BHBJO
CVU ZPVƊMM CF XSJUJOH OFX WFSTJPOT OPX 1MFBTF OPUF
UIFTF BSF BMM XSJUUFO BT UIFZ XPVME CF JO TPVSDF DPEF ƶMFT BOE
XF SFDPNNFOE ZPV XSJUF ZPVS BOTXFST JO TPVSDF ƶMFT BOE
UIFO MPBE JOUP ()$J UP DIFDL SBUIFS UIBO USZJOH UP EP UIFN
EJSFDUMZ JOUP UIF 3&1-
'JSTU SFXSJUF if-then-else FYQSFTTJPOT JOUP DBTF FYQSFTTJPOT
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 5IF GPMMPXJOH TIPVME SFUVSO x XIFO x JT HSFBUFS UIBO y

functionC x y = if (x > y) then x else y

 5IF GPMMPXJOH XJMM BEE  UP FWFO OVNCFST BOE PUIFSXJTF


TJNQMZ SFUVSO UIF JOQVU WBMVF

ifEvenAdd2 n = if even n then (n+2) else n

5IF OFYU FYFSDJTF EPFTOƊU IBWF BMM UIF DBTFT DPWFSFE 4FF
JG ZPV DBO ƶY JU

 5IF GPMMPXJOH DPNQBSFT B WBMVF x UP [FSP BOE SFUVSOT BO


JOEJDBUPS GPS XIFUIFS x JT B QPTUJWF OVNCFS PS OFHBUJWF
OVNCFS #VU XIBU JG x JT  :PV NBZ OFFE UP QMBZ XJUI
UIF compare GVODUJPO B CJU UP ƶOE XIBU UP EP

nums x =
case compare x 0 of
LT -> -1
GT -> 1

 )JHIFSPSEFS GVODUJPOT


)JHIFSPSEFS GVODUJPOT )0'T
BSF GVODUJPOT UIBU BDDFQU GVOD
UJPOT BT BSHVNFOUT 'VODUJPOT BSF KVTU WBMVFT ƈ XIZ DPVMEOƊU
UIFZ CF QBTTFE BSPVOE MJLF BOZ PUIFS WBMVFT 5IJT JT BO JN
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

QPSUBOU DPNQPOFOU PG GVODUJPOBM QSPHSBNNJOH BOE HJWFT VT


B XBZ UP DPNCJOF GVODUJPOT FƸDJFOUMZ
-FUƊT FYBNJOF B TUBOEBSE IJHIFSPSEFS GVODUJPO flip

Prelude> :t flip
flip :: (a -> b -> c) -> b -> a -> c

-- using (-) as our (a -> b -> c)


Prelude> (-) 10 1
9
Prelude> let fSub = flip (-)
Prelude> fSub 10 1
-9
Prelude> fSub 5 10
5

5IF ƶSTU QBSBNFUFS PG flip JT B GVODUJPO TVDI BT (-) UIBU


JUTFMG IBT UXP QBSBNFUFST flip ƷJQT UIF PSEFS PG UIF BSHVNFOUT
8F DBO JNQMFNFOU flip MJLF UIJT VTJOH UIF WBSJBCMF ԕ UP
SFQSFTFOU UIF GVODUJPO (a -> b -> c)

flip :: (a -> b -> c) -> b -> a -> c


flip f x y = f y x

"MUFSOBUFMZ JU DPVMEƊWF CFFO XSJUUFO BT

myFlip :: (a -> b -> c) -> b -> a -> c


myFlip f = \ x y -> f y x
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

5IFSFƊT OP EJƵFSFODF JO XIBU flip BOE myFlip EP POF EF


DMBSFT QBSBNFUFST JO UIF GVODUJPO EFƶOJUJPO BOE UIF PUIFS
EFDMBSFT UIFN JOTUFBE JO UIF BOPOZNPVT GVODUJPO WBMVF CFJOH
SFUVSOFE #VU XIBU NBLFT ƷJQ B IJHIFSPSEFS GVODUJPO 8FMM
JUƊT UIJT

flip :: (a -> b -> c) -> b -> a -> c


[ 1 ]
flip f x y = f y x
[2] [3]

 8IFO XF XBOU UP FYQSFTT B GVODUJPO BSHVNFOU XJUIJO B


GVODUJPO UZQF XF NVTU VTF QBSFOUIFTFT UP OFTU JU

 5IF BSHVNFOU ԕ JT UIF GVODUJPO a -> b -> c

 8F BQQMZ ԕ UP ԧ BOE Ԩ CVU flip XJMM ƷJQ UIF PSEFS PG BQ


QMJDBUJPO BOE BQQMZ ԕ UP Ԩ BOE UIFO ԧ JOTUFBE PG UIF VTVBM
PSEFS

5P CFUUFS VOEFSTUBOE IPX )0'T XPSL TZOUBDUJDBMMZ JUƊT


XPSUI SFNFNCFSJOH IPX QBSFOUIFTFT BTTPDJBUF JO UZQF TJHOB
UVSFT
-FUƊT MPPL BU UIF UZQF PG UIF GPMMPXJOH GVODUJPO

returnLast :: a -> b -> c -> d -> d


returnLast _ _ _ d = d
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

*G XF FYQMJDJUMZ QBSFOUIFTJ[F returnLast JU NVTU NBUDI UIF


BTTPDJBUJWJUZ PG -> XIJDI JT SJHIUBTTPDJBUJWF 5IF GPMMPXJOH
QBSFOUIFTJ[BUJPO XPSLT ƶOF /PUF UIBU UIJT NFSFMZ NBLFT UIF
EFGBVMU DVSSZJOH FYQMJDJU

returnLast' :: a -> (b -> (c -> (d -> d)))


returnLast' _ _ _ d = d

)PXFWFS UIJT XJMM OPU XPSL 5IJT JT OPU IPX -> BTTPDJBUFT

returnBroke :: (((a -> b) -> c) -> d) -> d


returnBroke _ _ _ d = d

*G ZPV BUUFNQU UP MPBE returnBroke ZPVƊMM HFU B UZQF FSSPS

Couldn't match expected type ‘t0 -> t1 -> t2 -> t2’


with actual type ‘d’

‘d’ is a rigid type variable bound by


the type signature for
returnBroke :: (((a -> b) -> c) -> d) -> d

Relevant bindings include


returnBroke :: (((a -> b) -> c) -> d) -> d

The equation(s) for ‘returnBroke’ have four arguments,


but its type ‘(((a -> b) -> c) -> d) -> d’
has only one
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

5IJT UZQF FSSPS JT UFMMJOH VT UIBU UIF UZQF PG returnBroke POMZ


TQFDJƶFT POF BSHVNFOU UIBU IBT UIF UZQF ((a -> b) -> c) -> d
ZFU PVS GVODUJPO EFƶOJUJPO TFFNT UP FYQFDU GPVS BSHVNFOUT
5IF UZQF TJHOBUVSF PG returnBroke TQFDJƶFT B TJOHMF GVODUJPO BT
UIF TPMF BSHVNFOU UP returnBroke
8F DBO IBWF B UZQF UIBU JT QBSFOUIFTJ[FE JO UIBU GBTIJPO BT
MPOH BT XF XBOU UP EP TPNFUIJOH EJƵFSFOU UIBO XIBU returnLast
EPFT

returnAfterApply :: (a -> b) -> a -> c -> b


returnAfterApply f a c = f a

8IBU XFƊSF EPJOH IFSF JT QBSFOUIFTJ[JOH UP UIF MFǕ TP UIBU


XF DBO SFGFS UP B TFQBSBUF GVODUJPO XJUI JUT PXO QBSBNFUFST
BOE SFTVMU BT BO BSHVNFOU UP PVS UPQ MFWFM GVODUJPO )FSF UIF
(a -> b) JT UIF ԕ BSHVNFOU XF VTF UP QSPEVDF B WBMVF PG UZQF ԑ
GSPN B WBMVF PG UZQF Ԑ
0OF SFBTPO XF XBOU )0'T JT UP NBOJQVMBUF IPX GVODUJPOT
BSF BQQMJFE UP BSHVNFOUT 5P VOEFSTUBOE BOPUIFS SFBTPO MFUƊT
SFWJTJU UIF compare GVODUJPO GSPN UIF Ord UZQFDMBTT

Prelude> :t compare
compare :: Ord a => a -> a -> Ordering
Prelude> :info Ordering
data Ordering = LT | EQ | GT

'VO GBDU returnBroke JT BO JNQPTTJCMF GVODUJPO
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

Prelude> compare 10 9
GT
Prelude> compare 9 9
EQ
Prelude> compare 9 10
LT

/PX XFƊMM XSJUF B GVODUJPO UIBU NBLFT VTF PG UIJT


$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

data Employee = Coder


| Manager
| Veep
| CEO
deriving (Eq, Ord, Show)

reportBoss :: Employee -> Employee -> IO ()


reportBoss e e' =
putStrLn $ show e ++ " is the boss of " ++ show e'

employeeRank :: Employee -> Employee -> IO ()


employeeRank e e' =
case compare e e' of
GT -> reportBoss e e'
-- [ 1 ]
EQ -> putStrLn "Neither employee is the boss"
-- [ 2 ]
LT -> (flip reportBoss) e e'
-- [ 3 ]

5IF case JO UIF employeeRank GVODUJPO JT B DBTF FYQSFTTJPO


5IJT GVODUJPO TBZT case expression

 *O UIF DBTF PG DPNQBSJOH F BOE FƊ BOE ƶOEJOH F JT HSFBUFS


UIBO FƊ SFUVSO reportBoss F FƊ
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 *O UIF DBTF PG ƶOEJOH UIFN FRVBM SFUVSO UIF TUSJOH ƌ/FJ


UIFS FNQMPZFF JT UIF CPTTƍ

 *O UIF DBTF PG ƶOEJOH F MFTT UIBO FƊ ƷJQ UIF GVODUJPO reportBoss


5IJT DPVME BMTP IBWF CFFO XSJUUFO reportBoss e' e

5IF compare GVODUJPO VTFT UIF CFIBWJPS PG UIF Ord JOTUBODF


EFƶOFE GPS B HJWFO UZQF JO PSEFS UP DPNQBSF UIFN *O UIJT
DBTF PVS EBUB EFDMBSBUJPO MJTUT UIFN JO PSEFS GSPN Coder JO
UIF MPXFTU SBOL BOE CEO JO UIF UPQ SBOL TP compare XJMM VTF UIBU
PSEFSJOH UP FWBMVBUF UIF SFTVMU PG UIF GVODUJPO
*G XF MPBE UIJT VQ BOE USZ JU PVU

Prelude> employeeRank Veep CEO


CEO is the boss of Veep

5IBUƊT QSPCBCMZ USVF JO NPTU DPNQBOJFT #FJOH JOEVTUSJPVT


QSPHSBNNFST XF OBUVSBMMZ XBOU UP SFGBDUPS UIJT B CJU UP CF
NPSF ƷFYJCMF ƈ OPUJDF IPX XF DIBOHF UIF UZQF PG employeeRank
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

data Employee = Coder


| Manager
| Veep
| CEO
deriving (Eq, Ord, Show)

reportBoss :: Employee -> Employee -> IO ()


reportBoss e e' =
putStrLn $ show e ++ " is the boss of " ++ show e'

employeeRank :: (Employee -> Employee -> Ordering)


-> Employee
-> Employee
-> IO ()
employeeRank f e e' =
case f e e' of
GT -> reportBoss e e'
EQ -> putStrLn "Neither employee is the boss"
LT -> (flip reportBoss) e e'

/PX PVS employeeRank GVODUJPO XJMM BDDFQU B GVODUJPO BSHV


NFOU XJUI UIF UZQF Employee -> Employee -> Ordering XIJDI XF
OBNFE ԕ JO UIF QMBDF XIFSF XF IBE compare CFGPSF :PVƊMM OP
UJDF XF IBWF UIF TBNF DBTF FYQSFTTJPOT IFSF BHBJO 8F DBO HFU
UIF TBNF CFIBWJPS XF IBE MBTU UJNF CZ KVTU QBTTJOH JU compare
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

BT UIF GVODUJPO BSHVNFOU

Prelude> employeeRank compare Veep CEO


CEO is the boss of Veep
Prelude> employeeRank compare CEO Veep
CEO is the boss of Veep

#VU TJODF XFƊSF DMFWFS IBDLFST XF DBO TVCWFSU UIF IJFSBSDIZ


XJUI B DPNQBSJTPO GVODUJPO UIBU EPFT TPNFUIJOH B CJU EJƵFSFOU
XJUI UIF GPMMPXJOH DPEF
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

data Employee = Coder


| Manager
| Veep
| CEO
deriving (Eq, Ord, Show)

reportBoss :: Employee -> Employee -> IO ()


reportBoss e e' =
putStrLn $ show e ++ " is the boss of " ++ show e'

codersRuleCEOsDrool :: Employee -> Employee -> Ordering


codersRuleCEOsDrool Coder Coder = EQ
codersRuleCEOsDrool Coder _ = GT
codersRuleCEOsDrool _ Coder = LT
codersRuleCEOsDrool e e' = compare e e'

employeeRank :: (Employee -> Employee -> Ordering)


-> Employee
-> Employee
-> IO ()
employeeRank f e e' =
case f e e' of
GT -> reportBoss e e'
EQ -> putStrLn "Neither employee is the boss"
LT -> (flip reportBoss) e e'
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

)FSF XFƊWF DSFBUFE B OFX GVODUJPO UIBU DIBOHFT UIF CFIBW


JPS PG UIF OPSNBM compare GVODUJPO CZ QBUUFSO NBUDIJOH PO
PVS EBUB DPOTUSVDUPS Coder *O B DBTF XIFSF Coder JT UIF ƶSTU
WBMVF BOE UIF TFDPOE WBMVF JT BOZUIJOH ƈ OPUF UIF VOEFSTDPSF
VTFE BT B DBUDIBMM
UIF SFTVMU XJMM CF GT PS HSFBUFS UIBO *O
B DBTF XIFSF Coder JT UIF TFDPOE WBMVF QBTTFE UIJT GVODUJPO
XJMM SFUVSO B LT PS MFTT UIBO SFTVMU *O BOZ DBTF XIFSF Coder JT
OPU POF PG UIF WBMVFT compare XJMM FYIJCJU JUT OPSNBM CFIBWJPS
5IF DBTF FYQSFTTJPO JO UIF employeeRank GVODUJPO JT PUIFSXJTF
VODIBOHFE
"OE IFSFƊT IPX UIBU XPSLT

Prelude> employeeRank compare Coder CEO


CEO is the boss of Coder
Prelude> employeeRank codersRuleCEOsDrool Coder CEO
Coder is the boss of CEO
Prelude> employeeRank codersRuleCEOsDrool CEO Coder
Coder is the boss of CEO

*G XF VTF compare BT PVS ԕ BSHVNFOU UIFO UIF CFIBWJPS


JT VODIBOHFE *G PO UIF PUIFS IBOE XF VTF PVS OFX GVOD
UJPO codersRuleCEOsDrool BT UIF ԕ BSHVNFOU UIFO UIF CFIBWJPS
DIBOHFT BOE XF VOMFBTI BOBSDIZ JO UIF DVCJDMF GBSN
8F XFSF BCMF UP SFMZ PO UIF CFIBWJPS PG compare CVU NBLF
DIBOHFT JO UIF QBSU XF XBOUFE UP DIBOHF 5IJT JT UIF WBMVF PG
)0'T 5IFZ HJWF VT UIF CFHJOOJOHT PG B QPXFSGVM NFUIPE GPS
SFVTJOH BOE DPNQPTJOH DPEF
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

&YFSDJTFT "SUGVM %PEHZ


(JWFO UIF GPMMPXJOH EFƶOJUJPOT UFMM VT XIBU WBMVF SFTVMUT GSPN
GVSUIFS BQQMJDBUJPOT 8IFO ZPVƊWF XSJUUFO EPXO BU MFBTU TPNF
PG UIF BOTXFST BOE UIJOL ZPV LOPX XIBUƊT XIBU UZQF UIF EFG
JOJUJPOT JOUP B ƶMF BOE MPBE UIFN JO ()$J UP UFTU ZPVS BOTXFST

-- Types not provided, try filling them in yourself.

dodgy x y = x + y * 10
oneIsOne = dodgy 1
oneIsTwo = (flip dodgy) 2

 'PS FYBNQMF HJWFO UIF FYQSFTTJPO dodgy 1 0 XIBU EP ZPV


UIJOL XJMM IBQQFO JG XF FWBMVBUF JU *G ZPV QVU UIF EFG
JOJUJPOT JO B ƶMF BOE MPBE UIFN JO ()$J ZPV DBO EP UIF
GPMMPXJOH UP TFF UIF SFTVMU

Prelude> dodgy 1 0
1

/PX BUUFNQU UP EFUFSNJOF XIBU UIF GPMMPXJOH FYQSFTTJPOT


SFEVDF UP %P JU JO ZPVS IFBE WFSJGZ JO ZPVS 3&1- BǒFS
ZPV UIJOL ZPV IBWF BO BOTXFS

 dodgy 1 1

 dodgy 2 2
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 dodgy 1 2

 dodgy 2 1

 oneIsOne 1

 oneIsOne 2

 oneIsTwo 1

 oneIsTwo 2

 oneIsOne 3

 oneIsTwo 3

 (VBSET
8F IBWF QMBZFE BSPVOE XJUI CPPMFBOT BOE FYQSFTTJPOT UIBU
FWBMVBUF UP UIFJS USVUI WBMVF JODMVEJOH if-then-else FYQSFTTJPOT
XIJDI SFMZ PO CPPMFBO FWBMVBUJPO UP EFDJEF CFUXFFO UXP PVU
DPNFT *O UIJT TFDUJPO XF XJMM MPPL BU BOPUIFS TZOUBDUJD QBUUFSO
DBMMFE HVBSET UIBU SFMJFT PO USVUI WBMVFT UP EFDJEF CFUXFFO UXP
PS NPSF QPTTJCMF SFTVMUT

JGUIFOFMTF
-FUƊT CFHJO XJUI B RVJDL SFWJFX PG XIBU XF MFBSOFE BCPVU
if-then-else FYQSFTTJPOT JO UIF #BTJD %BUBUZQFT DIBQUFS /PUF
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

if-then-else JT OPU HVBSET 8FƊSF KVTU SFWJFXJOH TPNFUIJOH TJN


JMBS CFGPSF NPWJOH PO UP HVBSET UIFNTFMWFT 5IF QBUUFSO JT
UIJT

if <condition>
then <result if True>
else <result if False>

XIFSF UIF if DPOEJUJPO JT BO FYQSFTTJPO UIBU SFTVMUT JO B Bool


WBMVF 8F TBX IPX UIJT BMMPXT VT UP XSJUF GVODUJPOT MJLF UIJT

Prelude> let x = 0
Prelude> if (x + 1 == 1) then "AWESOME" else "wut"
"AWESOME"

5IF OFYU DPVQMF PG FYBNQMFT XJMM EFNPOTUSBUF IPX UP VTF


UIF NVMUJMJOF CMPDL TZOUBY GPS BO if FYQSFTTJPO

-- alternately
Prelude> let x = 0
Prelude> :{
Prelude| if (x + 1 == 1)
Prelude| then "AWESOME"
Prelude| else "wut"
Prelude| :}
"AWESOME"

5IF JOEFOUBUJPO JTOƊU SFRVJSFE


$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

Prelude> let x = 0
Prelude> :{
Prelude| if (x + 1 == 1)
Prelude| then "AWESOME"
Prelude| else "wut"
Prelude| :}
"AWESOME"

*O UIF FYFSDJTFT BU UIF FOE PG $IBQUFS  ZPV XFSF BTLFE UP


XSJUF B GVODUJPO DBMMFE myAbs UIBU SFUVSOT UIF BCTPMVUF WBMVF PG
B SFBM OVNCFS :PV XPVME IBWF JNQMFNFOUFE UIBU GVODUJPO
XJUI BO if-then-else FYQSFTTJPO TJNJMBS UP UIF GPMMPXJOH

myAbs :: Integer -> Integer


myAbs x = if x < 0 then (-x) else x

8FƊSF HPJOH UP MPPL BU BOPUIFS XBZ UP XSJUF UIJT VTJOH HVBSET

8SJUJOH HVBSE CMPDLT


(VBSE TZOUBY BMMPXT VT UP XSJUF DPNQBDU GVODUJPOT UIBU BMMPX
GPS UXP PS NPSF QPTTJCMF PVUDPNFT EFQFOEJOH PO UIF USVUI PG
UIF DPOEJUJPOT -FUƊT TUBSU CZ MPPLJOH BU IPX XF XPVME XSJUF
myAbs XJUI B HVBSE CMPDL JOTUFBE PG XJUI BO if-then-else
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

myAbs :: Integer -> Integer


myAbs x
| x < 0 = (-x)
| otherwise = x

/PUJDF UIBU FBDI HVBSE IBT JUT PXO FRVBMT TJHO 8F EJEOƊU
QVU POF BǒFS UIF BSHVNFOU JO UIF ƶSTU MJOF PG UIF GVODUJPO EFG
JOJUJPO CFDBVTF FBDI DBTF OFFET JUT PXO FYQSFTTJPO UP SFUVSO
JG JUT CSBODI TVDDFFET /PX XFƊMM FOVNFSBUF UIF DPNQPOFOUT
GPS DMBSJUZ

myAbs :: Integer -> Integer


myAbs x
-- [1] [2]
| x < 0 = (-x)
-- [3] [4] [5] [6]
| otherwise = x
-- [7] [8] [9] [10]

 5IF OBNF PG PVS GVODUJPO myAbs TUJMM DPNFT ƶSTU

 5IFSF JT POF QBSBNFUFS OBNFE ԧ

 )FSFƊT XIFSF JU HFUT EJƵFSFOU 3BUIFS UIBO BO = JNNF


EJBUFMZ BǒFS UIF JOUSPEVDUJPO PG BOZ QBSBNFUFS T
XFƊSF
TUBSUJOH B OFX MJOF BOE VTJOH UIF QJQF | UP CFHJO B HVBSE
DBTF
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 5IJT JT UIF FYQSFTTJPO XFƊSF VTJOH UP UFTU UP TFF JG UIJT


CSBODI TIPVME CF FWBMVBUFE PS OPU 5IF HVBSE DBTF FY
QSFTTJPO CFUXFFO UIF | BOE = NVTU FWBMVBUF UP Bool

 5IF = EFOPUFT UIBU XFƊSF EFDMBSJOH XIBU FYQSFTTJPO UP


SFUVSO TIPVME PVS x < 0 CF True

 5IFO BǒFS UIF = XF IBWF UIF FYQSFTTJPO (-x) XIJDI XJMM


CF SFUVSOFE JG x < 0

 "OPUIFS OFX MJOF BOE B | UP CFHJO B OFX HVBSE DBTF

 otherwise JT KVTU BOPUIFS OBNF GPS True VTFE IFSF BT B


GBMMCBDL DBTF JO DBTF x < 0 XBT False

 "OPUIFS = UP CFHJO EFDMBSJOH UIF FYQSFTTJPO UP SFUVSO JG


XF IJU UIF otherwise DBTF

 8F LJDL ԧ CBDL PVU JG JU XBTOƊU MFTT UIBO 

-FUƊT TFF IPX UIJT FWBMVBUFT

*Main> myAbs (-10)


10
*Main> myAbs 10
10

*O UIF ƶSTU FYBNQMF XIFO JU JT QBTTFE B OFHBUJWF OVNCFS


BT BO BSHVNFOU JU MPPLT BU UIF ƶSTU HVBSE BOE TFFT UIBU (-10)
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

JT JOEFFE MFTT UIBO  FWBMVBUFT UIBU BT True BOE TP SFUVSOT


UIF SFTVMU PG (-x) JO UIJT DBTF (-(-10)) PS  *O UIF TFDPOE
FYBNQMF JU MPPLT BU UIF ƶSTU HVBSE TFFT UIBU  EPFT OPU NFFU
UIBU DPOEJUJPO TP JU JT False BOE HPFT UP UIF OFYU HVBSE 5IF
otherwise JT BMXBZT True TP JU SFUVSOT ԧ JO UIJT DBTF  (VBSET
BMXBZT FWBMVBUF TFRVFOUJBMMZ TP ZPVS HVBSET TIPVME CF PSEFSFE
GSPN UIF DBTF UIBU JT NPTU SFTUSJDUJWF UP UIF DBTF UIBU JT MFBTU
SFTUSJDUJWF
-FUƊT MPPL OFYU BU B GVODUJPO UIBU XJMM IBWF NPSF UIBO UXP
QPTTJCMF PVUDPNFT JO UIJT DBTF UIF SFTVMUT PG B UFTU PG TPEJVN
/B
MFWFMT JO UIF CMPPE 8F XBOU B GVODUJPO UIBU MPPLT BU UIF
OVNCFST UIF OVNCFST SFQSFTFOU N&R- PS NJMMJFRVJWBMFOUT
QFS MJUFS
BOE UFMMT VT JG UIF CMPPE TPEJVN MFWFMT BSF OPSNBM PS
OPU

bloodNa :: Integer -> String


bloodNa x
| x < 135 = "too low"
| x > 145 = "too high"
| otherwise = "just right"

8F DBO JODPSQPSBUF EJƵFSFOU UZQFT PG FYQSFTTJPOT JOUP UIF


HVBSE CMPDL BT MPOH BT FBDI HVBSE DBO CF FWBMVBUFE UP B Bool
WBMVF 'PS FYBNQMF UIF GPMMPXJOH UBLFT  OVNCFST BOE UFMMT
ZPV JG UIF USJBOHMF XIPTF TJEFT UIFZ NFBTVSF JT B SJHIU USJBOHMF
PS OPU VTJOH UIF 1ZUIBHPSFBO UIFPSFN

$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

-- c is the hypotenuse of the triangle. Google it.

isRight :: (Num a, Eq a) => a -> a -> a -> String


isRight a b c
| a^2 + b^2 == c^2 = "RIGHT ON"
| otherwise = "not right"

"OE UIF GPMMPXJOH GVODUJPO XJMM UBLF ZPVS EPHƊT BHF BOE UFMM
ZPV IPX PME ZPVS EPH JT JO IVNBO ZFBST

dogYrs :: Integer -> Integer


dogYrs x
| x <= 0 = 0
| x <= 1 = x * 15
| x <= 2 = x * 12
| x <= 4 = x * 8
| otherwise = x * 6

8IZ UIF EJƵFSFOU OVNCFST #FDBVTF QVQQJFT SFBDI NBUV


SJUZ NVDI GBTUFS UIBO IVNBO CBCJFT EP TP B ZFBSPME QVQQZ
JTOƊU BDUVBMMZ FRVJWBMFOU UP B  PS ZFBSPME DIJME UIFSF JT
NPSF DPNQMFYJUZ UP UIJT DPOWFSTJPO UIBO UIJT GVODUJPO VTFT
CFDBVTF PUIFS GBDUPST TVDI BT UIF TJ[F PG UIF EPH QMBZ B SPMF BT
XFMM :PV DBO DFSUBJOMZ FYQFSJNFOU XJUI UIBU JG ZPV MJLF

8F DBO BMTP VTF where EFDMBSBUJPOT XJUIJO HVBSE CMPDLT -FUƊT
TBZ ZPV HBWF B UFTU UIBU IBE  RVFTUJPOT BOE ZPV XBOUFE B
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

TJNQMF GVODUJPO GPS USBOTMBUJOH UIF OVNCFS PG RVFTUJPOT UIF


TUVEFOU HPU SJHIU JOUP B MFUUFS HSBEF

avgGrade :: (Fractional a, Ord a) => a -> Char


avgGrade x
| y >= 0.9 = 'A'
| y >= 0.8 = 'B'
| y >= 0.7 = 'C'
| y >= 0.59 = 'D'
| y < 0.59 = 'F'
where y = x / 100

/P TVSQSJTFT UIFSF /PUJDF UIF WBSJBCMF Ԩ JT JOUSPEVDFE OPU


BT BO BSHVNFOU UP UIF OBNFE GVODUJPO CVU JO UIF HVBSE CMPDL
BOE JT EFƶOFE JO UIF where DMBVTF #Z EFƶOJOH JU UIFSF JU JT JO
TDPQF GPS BMM UIF HVBSET BCPWF JU 5IFSF XFSF  QSPCMFNT PO
UIF IZQPUIFUJDBM UFTU TP BOZ ԧ XF HJWF JU XJMM CF EJWJEFE CZ 
UP SFUVSO UIF MFUUFS HSBEF
"MTP OPUJDF XF MFǒ PVU UIF otherwise XF DPVME IBWF VTFE JU
GPS UIF ƶOBM DBTF CVU DIPTF JOTUFBE UP VTF less than 5IBU JT ƶOF
CFDBVTF JO PVS HVBSET XFƊWF IBOEMFE BMM QPTTJCMF WBMVFT *U JT
JNQPSUBOU UP OPUF UIBU ()$J DBOOPU BMXBZT UFMM ZPV XIFO ZPV
IBWFOƊU BDDPVOUFE GPS BMM QPTTJCMF DBTFT BOE JU DBO CF EJƸDVMU
UP SFBTPO BCPVU JU TP JU JT XJTF UP VTF otherwise JO ZPVS ƶOBM
HVBSE
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

3FNFNCFS :PV DBO VTF :set -Wall JO ()$J UP UVSO PO


XBSOJOHT BOE UIFO JU XJMM UFMM ZPV JG ZPV IBWF OPOFYIBVTUJWF
QBUUFSOT

&YFSDJTFT (VBSE %VUZ


 *U JT QSPCBCMZ DMFBS UP ZPV XIZ ZPV XPVMEOƊU QVU BO otherwise
JO ZPVS UPQNPTU HVBSE CVU USZ JU XJUI avgGrade BOZXBZ
BOE TFF XIBU IBQQFOT *UƊMM CF NPSF DMFBS JG ZPV SFXSJUF
JU BT BO BDUVBM otherwise NBUDI | otherwise = 'F' 8IBU
IBQQFOT OPX JG ZPV QBTT B  BT BO BSHVNFOU  

 8IBU IBQQFOT JG ZPV UBLF avgGrade BT JU JT XSJUUFO BOE


SFPSEFS UIF HVBSET %PFT JU TUJMM UZQFDIFDL BOE XPSL UIF
TBNF 5SZ NPWJOH | y >= 0.7 = 'C' BOE QBTTJOH JU UIF
BSHVNFOU  XIJDI TIPVME CF BO Ɖ"Ɗ %PFT JU SFUVSO BO Ɖ"Ɗ

 5IF GPMMPXJOH GVODUJPO SFUVSOT

pal xs
| xs == reverse xs = True
| otherwise = False

B
xs XSJUUFO CBDLXBSET XIFO JUƊT True
C
True XIFO xs JT B QBMJOESPNF
D
False XIFO xs JT B QBMJOESPNF
E
False XIFO xs JT SFWFSTFE
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 8IBU UZQFT PG BSHVNFOUT DBO pal UBLF

 8IBU JT UIF UZQF PG UIF GVODUJPO pal

 5IF GPMMPXJOH GVODUJPO SFUVSOT

numbers x
| x < 0 = -1
| x == 0 = 0
| x > 0 = 1

B
UIF WBMVF PG JUT BSHVNFOU QMVT PS NJOVT 
C
UIF OFHBUJPO PG JUT BSHVNFOU
D
BO JOEJDBUJPO PG XIFUIFS JUT BSHVNFOU JT B QPTJUJWF PS
OFHBUJWF OVNCFS PS [FSP
E
CJOBSZ NBDIJOF MBOHVBHF

 8IBU UZQFT PG BSHVNFOUT DBO numbers UBLF

 8IBU JT UIF UZQF PG UIF GVODUJPO numbers

 'VODUJPO DPNQPTJUJPO


'VODUJPO DPNQPTJUJPO JT B UZQF PG IJHIFSPSEFS GVODUJPO UIBU
BMMPXT VT UP DPNCJOF GVODUJPOT TVDI UIBU UIF SFTVMU PG BQQMZJOH
POF GVODUJPO HFUT QBTTFE UP UIF OFYU GVODUJPO BT BO BSHVNFOU
*U JT B WFSZ DPODJTF TUZMF JO LFFQJOH XJUI UIF UFSTF GVODUJPOBM
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

TUZMF )BTLFMM JT LOPXO GPS "U ƶSTU JU TFFNT DPNQMJDBUFE BOE


EJƸDVMU UP VOQBDL CVU PODF ZPV HFU UIF IBOH PG JU JUƊT GVO
-FUƊT CFHJO CZ MPPLJOH BU UIF UZQF TJHOBUVSF BOE XIBU JU NFBOT

(.) :: (b -> c) -> (a -> b) -> a -> c


-- [1] [2] [3] [4]

 JT B GVODUJPO GSPN ԑ UP Ԓ QBTTFE BT BO BSHVNFOU UIVT UIF


QBSFOUIFTFT

 JT B GVODUJPO GSPN Ԑ UP ԑ

 JT B WBMVF PG UZQF Ԑ UIF TBNF BT [2] FYQFDUT BT BO BSHVNFOU

 JT B WBMVF PG UZQF Ԓ UIF TBNF BT [1] SFUVSOT BT B SFTVMU

5IFO XJUI UIF BEEJUJPO PG POF TFU PG QBSFOUIFTFT

(.) :: (b -> c) -> (a -> b) -> (a -> c)


-- [1] [2] [3]

*O &OHMJTI

 HJWFO B GVODUJPO ԑ UP Ԓ

 HJWFO B GVODUJPO Ԑ UP ԑ

 SFUVSO B GVODUJPO Ԑ UP Ԓ
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

5IF SFTVMU PG (a -> b) JT UIF BSHVNFOU PG (b -> c) TP UIJT JT


IPX XF HFU GSPN BO Ԑ BSHVNFOU UP B Ԓ SFTVMU 8FƊWF TUJUDIFE
UIF SFTVMU PG POF GVODUJPO JOUP CFJOH UIF BSHVNFOU PG BOPUIFS
/FYU MFUƊT TUBSU MPPLJOH BU DPNQPTFE GVODUJPOT BOE IPX
UP SFBE BOE XPSL XJUI UIFN 5IF CBTJD TZOUBY PG GVODUJPO
DPNQPTJUJPO MPPLT MJLF UIJT

(f . g) x = f (g x)

5IJT DPNQPTJUJPO PQFSBUPS (.) UBLFT UXP GVODUJPOT IFSF


OBNFE ԕ BOE Ԗ 5IF ԕ GVODUJPO DPSSFTQPOET UP UIF (b -> c) JO
UIF UZQF TJHOBUVSF XIJMF UIF Ԗ GVODUJPO DPSSFTQPOET UP UIF
(a -> b) 5IF Ԗ GVODUJPO JT BQQMJFE UP UIF QPMZNPSQIJD
ԧ
BSHVNFOU 5IF SFTVMU PG UIBU BQQMJDBUJPO UIFO QBTTFT UP UIF ԕ
GVODUJPO BT JUT BSHVNFOU 5IF ԕ GVODUJPO JT JO UVSO BQQMJFE UP
UIBU BSHVNFOU BOE FWBMVBUFE UP SFBDI UIF ƶOBM SFTVMU
-FUƊT HP TUFQ CZ TUFQ UISPVHI UIJT USBOTGPSNBUJPO 8F DBO
UIJOL PG UIF (.) PS DPNQPTJUJPO PQFSBUPS BT CFJOH B XBZ PG
QJQFMJOJOH EBUB UISPVHI NVMUJQMF GVODUJPOT 5IF GPMMPXJOH
DPNQPTFE GVODUJPOT XJMM ƶSTU BEE UIF WBMVFT JO UIF MJTU UPHFUIFS
BOE UIFO OFHBUF UIF SFTVMU PG UIBU

Prelude> negate . sum $ [1, 2, 3, 4, 5]


-15

-- which is evaluated like this


negate . sum $ [1, 2, 3, 4, 5]
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

-- note: this code works as well


negate (sum [1, 2, 3, 4, 5])
negate (15)
-15

/PUJDF UIBU XF EJE UIJT EJSFDUMZ JO PVS 3&1- CFDBVTF UIF


DPNQPTJUJPO PQFSBUPS JT BMSFBEZ JO TDPQF JO Prelude 5IF TVN
PG UIF MJTU JT  5IBU SFTVMU HFUT QBTTFE UP UIF negate GVODUJPO
BOE SFUVSOT B SFTVMU PG -15
:PV NBZ CF XPOEFSJOH XIZ XF OFFE UIF $ PQFSBUPS :PV
NJHIU SFNFNCFS XBZ CBDL XIFO XF UBMLFE BCPVU UIF QSFDF
EFODF PG WBSJPVT PQFSBUPST UIBU XF TBJE UIBU PQFSBUPS IBT B
MPXFS QSFDFEFODF UIBO BO PSEJOBSZ GVODUJPO DBMM XIJUF TQBDF
VTVBMMZ
 0SEJOBSZ GVODUJPO BQQMJDBUJPO IBT B QSFDFEFODF PG
 PVU PG 
 5IF DPNQPTJUJPO PQFSBUPS IBT B QSFDFEFODF PG
 *G XF MFǒ XIJUF TQBDF BT PVS GVODUJPO BQQMJDBUJPO UIJT XPVME
CF FWBMVBUFE MJLF UIJT

negate . sum [1, 2, 3, 4, 5]


negate . 15

#FDBVTF GVODUJPO BQQMJDBUJPO IBT B IJHIFS QSFDFEFODF UIBO


UIF DPNQPTJUJPO PQFSBUPS UIBU GVODUJPO BQQMJDBUJPO XPVME
IBQQFO CFGPSF UIF UXP GVODUJPOT DPNQPTFE 8FƊE CF USZJOH UP
QBTT B OVNFSJD WBMVF XIFSF PVS DPNQPTJUJPO PQFSBUPS OFFET B
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

GVODUJPO #Z VTJOH UIF $ XF TJHOBM UIBU BQQMJDBUJPO UP UIF BSHV


NFOUT TIPVME IBQQFO BǕFS UIF GVODUJPOT BSF BMSFBEZ DPNQPTFE

8F DBO BMTP QBSFOUIFTJ[F JU JOTUFBE PG VTJOH UIF $ PQFSBUPS


*O UIBU DBTF JU MPPLT MJLF UIJT

Prelude> (negate . sum) [1, 2, 3, 4, 5]


-15

5IF DIPJDF PG XIFUIFS UP VTF QBSFOUIFTFT PS UIF EPMMBS TJHO


JTOƊU JNQPSUBOU JU JT KVTU B RVFTUJPO PG TUZMF BOE FBTF PG XSJUJOH
BOE SFBEJOH
5IF OFYU FYBNQMF VTFT UXP GVODUJPOT take BOE reverse BOE
JT BQQMJFE UP BO BSHVNFOU UIBU JT B MJTU PG OVNCFST GSPN  UP 
8IBU XF FYQFDU UP IBQQFO JT UIBU UIF MJTU XJMM ƶSTU CF SFWFSTFE
GSPN  UP 
BOE UIFO UIF ƶSTU  FMFNFOUT PG UIF OFX MJTU XJMM
CF SFUVSOFE BT UIF SFTVMU

Prelude> take 5 . reverse $ [1..10]


[10,9,8,7,6]

(JWFO UIF OFYU CJU PG DPEF IPX DPVME XF SFXSJUF JU UP VTF


GVODUJPO DPNQPTJUJPO JOTUFBE PG QBSFOUIFTFT

Prelude> take 5 (enumFrom 3)


[3,4,5,6,7]
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

8F LOPX UIBU XF XJMM IBWF UP FMJNJOBUF UIF QBSFOUIFTFT


BEE UIF DPNQPTJUJPO PQFSBUPS BOE BEE UIF $ PQFSBUPS *U XJMM
UIFO MPPL MJLF UIJT

Prelude> take 5 . enumFrom $ 3


[3,4,5,6,7]

:PV NBZ BMTP EFƶOF JU UIJT XBZ XIJDI JT NPSF TJNJMBS UP


IPX DPNQPTJUJPO JT XSJUUFO JO TPVSDF ƶMFT

Prelude> let f x = take 5 . enumFrom $ x


Prelude> f 3
[3,4,5,6,7]

:PV NBZ CF XPOEFSJOH XIZ CPUIFS XJUI UIJT JG JU TJNQMZ


EPFT UIF TBNF UIJOH BT OFTUJOH GVODUJPOT JO QBSFOUIFTFT 0OF
SFBTPO JT UIBU JU JT RVJUF FBTZ UP DPNQPTF NPSF UIBO UXP GVOD
UJPOT UIJT XBZ
5IF filter odd GVODUJPO JT OFX GPS VT CVU JU TJNQMZ ƶMUFST UIF
PEE OVNCFST ZPV DBO DIBOHF JU UP filter even JG ZPV XJTI
PVU
PG UIF MJTU UIBU enumFrom CVJMET GPS VT 'JOBMMZ take XJMM SFUVSO
BT UIF SFTVMU POMZ UIF OVNCFS PG FMFNFOUT XF IBWF TQFDJƶFE
BT UIF BSHVNFOU PG take 'FFM GSFF UP FYQFSJNFOU XJUI WBSZJOH
BOZ PG UIF BSHVNFOUT

Prelude> take 5 . filter odd . enumFrom $ 3


[3,5,7,9,11]
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

"T ZPV DPNQPTF NPSF GVODUJPOT ZPV DBO TFF UIBU OFTUJOH
BMM UIF QBSFOUIFTFT XPVME CFDPNF UJSFTPNF 5IJT PQFSBUPS
BMMPXT VT UP EP BXBZ XJUI UIBU *U BMTP BMMPXT VT UP XSJUF JO BO
FWFO NPSF UFSTF TUZMF LOPXO BT ƌQPJOUGSFFƍ

 1PJOUGSFF TUZMF


1PJOUGSFF SFGFST UP B TUZMF PG DPNQPTJOH GVODUJPOT XJUIPVU
TQFDJGZJOH UIFJS BSHVNFOUT 5IF ƌQPJOUƍ JO ƌQPJOUGSFFƍ SFGFST
UP UIF BSHVNFOUT OPU BT JU NBZ TFFN
UP UIF GVODUJPO DPNQP
TJUJPO PQFSBUPS *O TPNF TFOTF XF BEE ƌQPJOUTƍ UIF PQFSBUPS

UP CF BCMF UP ESPQ QPJOUT BSHVNFOUT


 2VJUF PǒFO QPJOUGSFF
DPEF JT UJEJFS PO UIF QBHF BOE FBTJFS UP SFBE BT JU IFMQT UIF
SFBEFS GPDVT PO UIF GVODUJPOT SBUIFS UIBO UIF EBUB UIBU JT CFJOH
TIVƹFE BSPVOE
8F TBJE BCPWF UIBU GVODUJPO DPNQPTJUJPO MPPLT MJLF UIJT

(f . g) x = f (g x)

"T ZPV QVU NPSF GVODUJPOT UPHFUIFS DPNQPTJUJPO DBO NBLF


UIFN FBTJFS UP SFBE 'PS FYBNQMF (f. g. h) x DBO CF FBTJFS UP
SFBE UIBO f (g (h x)) BOE JU BMTP CSJOHT UIF GPDVT UP UIF GVOD
UJPOT SBUIFS UIBO UIF BSHVNFOUT 1PJOUGSFF JT KVTU BO FYUFOTJPO
PG UIBU JEFB CVU OPX XF ESPQ UIF BSHVNFOUT BMUPHFUIFS

f . g = \x -> f (g x)
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

f . g . h = \x -> f (g (h x))

5P TFF XIBU UIJT MPPLT MJLF JO QSBDUJDF XFƊMM TUBSU CZ SFXSJUJOH


JO QPJOUGSFF TUZMF TPNF PG UIF GVODUJPOT XF VTFE JO UIF TFDUJPO
BCPWF

Prelude> let f = negate . sum


Prelude> f [1, 2, 3, 4, 5]
-15

/PUJDF UIBU XIFO XF EFƶOF PVS GVODUJPO f XF EPOƊU TQFD


JGZ UIBU UIFSF XJMM CF BOZ BSHVNFOUT :FU XIFO XF BQQMZ UIF
GVODUJPO UP BO BSHVNFOU UIF TBNF UIJOH IBQQFOT BT CFGPSF
)PX XPVME XF SFXSJUF

f :: Int -> [Int] -> Int


f z xs = foldr (+) z xs

BT B QPJOUGSFF GVODUJPO

Prelude> let f = foldr (+)


Prelude> f 0 [1..5]
15

"OE OPX CFDBVTF XF OBNFE UIF GVODUJPO JU DBO CF SFVTFE


XJUI EJƵFSFOU BSHVNFOUT
)FSF JT BOPUIFS FYBNQMF PG B TIPSU QPJOUGSFF GVODUJPO BOE
JUT SFTVMU *U JOWPMWFT B OFX VTF PG filter UIBU VTFT UIF Bool
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

PQFSBUPS == -PPL BU JU DBSFGVMMZ BOE PO QBQFS PS JO ZPVS IFBE


XBML UISPVHI UIF FWBMVBUJPO QSPDFTT JOWPMWFE

Prelude> let f = length . filter (== 'a')


Prelude> f "abracadabra"
5

/FYU XFƊMM MPPL BU B TFU PG GVODUJPOT UIBU XPSL UPHFUIFS JO B


TJOHMF NPEVMF BOE SFMZ PO CPUI DPNQPTJUJPO BOE QPJOUGSFF
TUZMF

-- arith2.hs
module Arith2 where

add :: Int -> Int -> Int


add x y = x + y

addPF :: Int -> Int -> Int


addPF = (+)

addOne :: Int -> Int


addOne = \x -> x + 1

addOnePF :: Int -> Int


addOnePF = (+1)
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

main :: IO ()
main = do
print (0 :: Int)
print (add 1 0)
print (addOne 0)
print (addOnePF 0)
print ((addOne . addOne) 0)

print ((addOnePF . addOne) 0)


print ((addOne . addOnePF) 0)
print ((addOnePF . addOnePF) 0)
print (negate (addOne 0))
print ((negate . addOne) 0)
print ((addOne . addOne . addOne
. negate . addOne) 0)

5BLF ZPVS UJNF BOE XPSL UISPVHI XIBU FBDI GVODUJPO JT


EPJOH XIFUIFS PO QBQFS PS JO ZPVS IFBE 5IFO MPBE UIJT DPEF
BT B TPVSDF ƶMF BOE SVO JU JO ()$ BOE TFF JG ZPVS SFTVMUT XFSF
BDDVSBUF
:PV TIPVME OPX IBWF B HPPE VOEFSTUBOEJOH PG IPX ZPV
DBO VTF (.) UP DPNQPTF GVODUJPOT *UƊT JNQPSUBOU UP SFNFNCFS
UIBU UIF GVODUJPOT JO DPNQPTJUJPO BSF BQQMJFE GSPN SJHIU UP
MFǒ MJLF B 1BDNBO NVODIJOH GSPN UIF SJHIU TJEF SFEVDJOH UIF
FYQSFTTJPOT BT IF HPFT
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 %FNPOTUSBUJOH DPNQPTJUJPO


:PV NBZ SFDBMM UIBU CBDL JO UIF DIBQUFS PO 1SJOUJOH 4USJOHT XF
NFOUJPOFE UIBU UIF GVODUJPOT print BOE putStr TFFN TJNJMBS PO
UIF TVSGBDF CVU CFIBWF EJƵFSFOUMZ CFDBVTF UIFZ IBWF EJƵFSFOU
VOEFSMZJOH UZQFT -FUƊT UBLF B DMPTFS MPPL BU UIBU OPX
'JSTU putStrLn BOE putStr IBWF UIF TBNF UZQF

putStr :: String -> IO ()


putStrLn :: String -> IO ()

#VU UIF UZQF PG print JT EJƵFSFOU

print :: Show a => a -> IO ()

5IFZ BMM SFUVSO B SFTVMU PG IO () GPS SFBTPOT XF EJTDVTTFE


JO UIF QSFWJPVT DIBQUFS #VU UIF QBSBNFUFST IFSF BSF RVJUF
EJƵFSFOU 5IF ƶSTU UXP UBLF StringT BT BSHVNFOUT XIJMF print
IBT B DPOTUSBJOFE QPMZNPSQIJD QBSBNFUFS Show a => a 5IF
ƶSTU UXP XPSL ƶOF UIFO JG XIBU XF OFFE UP EJTQMBZ PO UIF
TDSFFO BSF BMSFBEZ TUSJOHT CVU IPX EP XF EJTQMBZ OVNCFST
PS PUIFS OPOTUSJOH WBMVFT
'JSTU XF IBWF UP DPOWFSU UIPTF
OVNCFST UP TUSJOHT UIFO XF DBO QSJOU UIF TUSJOHT
:PV NBZ BMTP SFDBMM B GVODUJPO GSPN PVS EJTDVTTJPO PG UIF
Show UZQFDMBTT DBMMFE show )FSFƊT UIF UZQF PG show BHBJO

show :: Show a => a -> String


$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

'PSUVOBUFMZ JU XBT VOEFSTUPPE UIBU DPNCJOJOH putStrLn BOE


show XPVME CF B DPNNPO QBUUFSO TP UIF GVODUJPO OBNFE print
JT UIF DPNQPTJUJPO PG show BOE putStrLn 8F EP JU UIJT XBZ
CFDBVTF JUƊT TJNQMFS 5IF QSJOUJOH GVODUJPO DPODFSOT JUTFMG POMZ
XJUI QSJOUJOH XIJMF UIF TUSJOHJƶDBUJPO GVODUJPO DPODFSOT JUTFMG
POMZ XJUI UIBU
)FSF BSF UXP XBZT UP JNQMFNFOU print XJUI putStrLn BOE
show

print :: Show a => a -> IO ()


print a = putStrLn (show a)

-- using the . operator for composing functions.


(.) :: (b -> c) -> (a -> b) -> a -> c

-- we can write print as:


print :: Show a => a -> IO ()
print a = (putStrLn . show) a

/PX MFUƊT HP TUFQ CZ TUFQ UISPVHI UIJT VTF PG (.) putStrLn


BOE show

(.) :: (b -> c) -> (a -> b) -> a -> c

putStrLn :: String -> IO ()


-- [1] [2]
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

show :: Show a => a -> String


-- [3] [4]

putStrLn . show :: Show a => a -> IO ()


-- [5] [6]

(.) :: (b -> c) -> (a -> b) -> a -> c


-- [1] [2] [3] [4] [5] [6]

-- If we replace the variables with the specific


-- types they take on in this application of (.)

(.) :: Show a => (String -> IO ())


-> (a -> String)
-> a -> IO ()

(.) :: (b -> c)
-- (String -> IO ())

-> (a -> b)
-- (a -> String)

-> a -> c
-- a -> IO ()

 JT UIF 4USJOH UIBU putStrLn BDDFQUT BT BO BSHVNFOU


$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 JT UIF IO () UIBU putStrLn SFUVSOT UIBU JT QFSGPSNJOH UIF


TJEF FƵFDU PG QSJOUJOH BOE SFUVSOJOH VOJU

 JT Ԑ XIP NVTU JNQMFNFOU UIF 4IPX UZQFDMBTT UIJT JT UIF


Show a => a GSPN UIF show GVODUJPO XIJDI JT B NFUIPE PO
UIF 4IPX UZQFDMBTT

 JT UIF 4USJOH XIJDI TIPX SFUVSOT 5IJT JT XIBU UIF Show a


=> a WBMVF HPU TUSJOHJƶFE JOUP

 JT UIF Show a => a UIF ƶOBM DPNQPTFE GVODUJPO FYQFDUT

 JT UIF IO () UIF ƶOBM DPNQPTFE GVODUJPO SFUVSOT

8F DBO OPX NBLF JU QPJOUGSFF 8IFO XF BSF XPSLJOH XJUI


GVODUJPOT QSJNBSJMZ JO UFSNT PG DPNQPTJUJPO SBUIFS UIBO BQQMJ
DBUJPO UIF QPJOUGSFF WFSTJPO DBO PǒFO OPU BMXBZT
CF NPSF
FMFHBOU
)FSFƊT UIF QPJOUGSFF WFSTJPO PG print

-- Previous version of the function


print :: Show a => a -> IO ()
print a = (putStrLn . show) a

print :: Show a => a -> IO ()


print = putStrLn . show

5IF QPJOU PG print JT UP DPNQPTF putStrLn BOE show TP UIBU


XF EPOƊU IBWF UP DBMM show PO JUT BSHVNFOU PVSTFMWFT 5IBU JT
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

print JT QSJODJQBMMZ BCPVU UIF DPNQPTJUJPO PG UXP GVODUJPOT


TP JU DPNFT PVU OJDFMZ BT B QPJOUGSFF GVODUJPO 4BZJOH UIBU
XF DPVME BQQMZ putStrLn . show UP BO BSHVNFOU JO UIJT DBTF JT
SFEVOEBOU

 $IBQUFS &YFSDJTFT


.VMUJQMF DIPJDF
 " QPMZNPSQIJD GVODUJPO

B
DIBOHFT UIJOHT JOUP TIFFQ XIFO JOWPLFE
C
IBT NVMUJQMF BSHVNFOUT
D
IBT B DPODSFUF UZQF
E
NBZ SFTPMWF UP WBMVFT PG EJƵFSFOU UZQFT EFQFOEJOH
PO JOQVUT

 5XP GVODUJPOT OBNFE f BOE g IBWF UZQFT Char -> String


BOE String -> [String] SFTQFDUJWFMZ 5IF DPNQPTFE GVOD
UJPO g . f IBT UIF UZQF

B
Char -> String
C
Char -> [String]
D
[[String]]
E
Char -> String -> [String]
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 " GVODUJPO f IBT UIF UZQF Ord a => a -> a -> Bool BOE XF
BQQMZ JU UP POF OVNFSJD WBMVF 8IBU JT UIF UZQF OPX

B
Ord a => a -> Bool
C
Num -> Num -> Bool
D
Ord a => a -> a -> Integer
E
(Ord a, Num a) => a -> Bool

 " GVODUJPO XJUI UIF UZQF (a -> b) -> c

B
SFRVJSFT WBMVFT PG UISFF EJƵFSFOU UZQFT
C
JT B IJHIFSPSEFS GVODUJPO
D
NVTU UBLF B UVQMF BT JUT ƶSTU BSHVNFOU
E
IBT JUT QBSBNFUFST JO BMQIBCFUJDBM PSEFS

 (JWFO UIF GPMMPXJOH EFƶOJUJPO PG f XIBU JT UIF UZQF PG f


True

f :: a -> a
f x = x

B
f True :: Bool
C
f True :: String
D
f True :: Bool -> Bool
E
f True :: a
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

-FUƊT XSJUF DPEF


 5IF GPMMPXJOH GVODUJPO SFUVSOT UIF UFOT EJHJU PG BO JOUFHSBM
BSHVNFOU

tensDigit :: Integral a => a -> a


tensDigit x = d
where xLast = x `div` 10
d = xLast `mod` 10

B
'JSTU SFXSJUF JU VTJOH divMod
C
%PFT UIF divMod WFSTJPO IBWF UIF TBNF UZQF BT UIF
PSJHJOBM WFSTJPO
D
/FYU MFUƊT DIBOHF JU TP UIBU XFƊSF HFUUJOH UIF IVOESFET
EJHJU JOTUFBE :PV DPVME TUBSU JU MJLF UIJT UIPVHI UIBU
NBZ OPU CF UIF POMZ QPTTJCJMJUZ


hunsD x = d2
where d = undefined
...

 *NQMFNFOU UIF GVODUJPO PG UIF UZQF a -> a -> Bool -> a


PODF FBDI VTJOH B DBTF FYQSFTTJPO BOE PODF XJUI B HVBSE

foldBool :: a -> a -> Bool -> a


foldBool = error "Error: Need to implement foldBool!"
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

5IF SFTVMU JT TFNBOUJDBMMZ TJNJMBS UP if-then-else FYQSFT


TJPOT CVU TZOUBDUJDBMMZ RVJUF EJƵFSFOU )FSF JT UIF QBUUFSO
NBUDIJOH WFSTJPO UP HFU ZPV TUBSUFE

foldBool3 :: a -> a -> Bool -> a


foldBool3 x y True = x
foldBool3 x y False = y

 'JMM JO UIF EFƶOJUJPO /PUF UIBU UIF ƶSTU BSHVNFOU UP PVS


GVODUJPO JT BMTP B GVODUJPO XIJDI DBO CF BQQMJFE UP WBMVFT
:PVS TFDPOE BSHVNFOU JT B UVQMF XIJDI DBO CF VTFE GPS
QBUUFSO NBUDIJOH

g :: (a -> b) -> (a, c) -> (b, c)


g = undefined

 'PS UIJT OFYU FYFSDJTF ZPVƊMM FYQFSJNFOU XJUI XSJUJOH


QPJOUGSFF WFSTJPOT PG FYJTUJOH DPEF 5IJT JOWPMWFT TPNF
OFX JOGPSNBUJPO TP SFBE UIF GPMMPXJOH FYQMBOBUJPO DBSF
GVMMZ
5ZQFDMBTTFT BSF EJTQBUDIFE CZ UZQF Read JT B UZQFDMBTT MJLF
Show CVU JU JT UIF EVBM PS ƌPQQPTJUFƍ PG Show *O HFOFSBM UIF
Read UZQFDMBTT JTOƊU TPNFUIJOH ZPV TIPVME QMBO UP VTF B
MPU CVU UIJT FYFSDJTF JT TUSVDUVSFE UP UFBDI ZPV TPNFUIJOH
BCPVU UIF JOUFSBDUJPO CFUXFFO UZQFDMBTTFT BOE UZQFT
5IF GVODUJPO read JO UIF Read UZQFDMBTT IBT UIF UZQF
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

read :: Read a => String -> a

/PUJDF B QBUUFSO

read :: Read a => String -> a


show :: Show a => a -> String

8SJUF UIF GPMMPXJOH DPEF JOUP B TPVSDF ƶMF 5IFO MPBE JU


BOE SVO JU JO ()$J UP NBLF TVSF ZPV VOEFSTUBOE XIZ UIF
FWBMVBUJPO SFTVMUT JO UIF BOTXFST ZPV TFF

-- arith4.hs
module Arith4 where

-- id :: a -> a
-- id x = x

roundTrip :: (Show a, Read a) => a -> a


roundTrip a = read (show a)

main = do
print (roundTrip 4)
print (id 4)

 /FYU XSJUF B QPJOUGSFF WFSTJPO PG roundTrip OC UIJT


SFGFST UP UIF GVODUJPO EFƶOJUJPO OPU UP JUT BQQMJDBUJPO JO
main

$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 8F XJMM DPOUJOVF UP VTF UIF DPEF JO module Arith4 GPS UIJT


FYFSDJTF BT XFMM
8IFO XF BQQMZ show UP B WBMVF TVDI BT (1 :: Int) UIF Ԑ UIBU
JNQMFNFOUT 4IPX JT *OU TP ()$ XJMM VTF UIF *OU JOTUBODF
PG UIF 4IPX UZQFDMBTT UP TUSJOHJGZ PVS *OU PG 
)PXFWFS read FYQFDUT B String BSHVNFOU JO PSEFS UP SF
UVSO BO Ԑ 5IF String BSHVNFOU UIBU JT UIF ƶSTU BSHVNFOU
UP read UFMMT UIF GVODUJPO OPUIJOH BCPVU XIBU UZQF UIF EF
TUSJOHJƶFE SFTVMU TIPVME CF *O UIF UZQF TJHOBUVSF roundTrip
DVSSFOUMZ IBT JU LOPXT CFDBVTF UIF UZQF WBSJBCMFT BSF UIF
TBNF TP UIF UZQF UIBU JT UIF JOQVU UP show IBT UP CF UIF
TBNF UZQF BT UIF PVUQVU PG read
:PVS UBTL OPX JT UP DIBOHF UIF UZQF PG roundTrip JO Arith4 UP
(Show a, Read b) => a -> b )PX NJHIU XF UFMM ()$ XIJDI
JOTUBODF PG Read UP EJTQBUDI BHBJOTU UIF String OPX .BLF
UIF FYQSFTTJPO print (roundTrip 4) XPSL :PV XJMM POMZ
OFFE UIF IBT UIF UZQF TZOUBY PG :: BOE QBSFOUIFTFT GPS
TDPQJOH

 $IBQUFS %FƶOJUJPOT


 #JOEJOH PS CPVOE JT B DPNNPO XPSE VTFE UP JOEJDBUF DPO
OFDUJPO MJOLBHF PS BTTPDJBUJPO CFUXFFO UXP PCKFDUT *O
)BTLFMM XFƊMM VTF JU UP UBML BCPVU XIBU WBMVF B WBSJBCMF IBT
FH B QBSBNFUFS WBSJBCMF JT CPVOE UP BO BSHVNFOU WBMVF
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

NFBOJOH UIF WBMVF JT QBTTFE JOUP UIF QBSBNFUFS BT JOQVU


BOE FBDI PDDVSSFODF PG UIBU OBNFE QBSBNFUFS XJMM IBWF
UIF TBNF WBMVF #JOEJOHT BT B QMVSBMJUZ XJMM VTVBMMZ SFGFS
UP B DPMMFDUJPO PG WBSJBCMFT BOE GVODUJPOT XIJDI DBO CF
SFGFSFODFE CZ OBNF

blah :: Int
blah = 10

)FSF UIF WBSJBCMF blah JT CPVOE UP UIF WBMVF 10

 "O BOPOZNPVT GVODUJPO JT B GVODUJPO XIJDI JT OPU CPVOE UP


BO JEFOUJƶFS BOE JT JOTUFBE QBTTFE BT BO BSHVNFOU UP BO
PUIFS GVODUJPO BOEPS VTFE UP DPOTUSVDU BOPUIFS GVODUJPO
4FF UIF GPMMPXJOH FYBNQMFT

\x -> x
-- anonymous version of id

id x = x
-- not anonymous, it's bound to 'id'

 $VSSZJOH JT UIF QSPDFTT PG USBOTGPSNJOH B GVODUJPO UIBU


UBLFT NVMUJQMF BSHVNFOUT JOUP B TFSJFT PG GVODUJPOT XIJDI
FBDI UBLF POF BSHVNFOU BOE SFUVSO POF SFTVMU 5IJT JT BD
DPNQMJTIFE UISPVHI UIF OFTUJOH *O )BTLFMM BMM GVODUJPOT
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

BSF DVSSJFE CZ EFGBVMU :PV EPOƊU OFFE UP EP BOZUIJOH


TQFDJBM ZPVSTFMG

-- curry and uncurry already exist in Prelude

curry' :: ((a, b) -> c) -> a -> b -> c


curry' f a b = f (a, b)

uncurry' :: (a -> b -> c) -> ((a, b) -> c)


uncurry' f (a, b) = f a b

-- uncurried function, takes a tuple of its arguments


add :: (Int, Int) -> Int
add (x, y) = x + y

add' :: Int -> Int -> Int


add' = curry' add

" GVODUJPO UIBU BQQFBST UP UBLF UXP BSHVNFOUT JT BDUVBMMZ


UXP GVODUJPOT UIBU FBDI UBLF POF BSHVNFOU BOE SFUVSO
POF SFTVMU 8IBU NBLFT UIJT XPSL JT UIBU B GVODUJPO DBO
SFUVSO BOPUIFS GVODUJPO
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

f a b = a + b

-- is equivalent to

f = \a -> (\b -> a + b)

 1BUUFSO NBUDIJOH JT B TZOUBDUJD XBZ PG EFDPOTUSVDUJOH QSPE


VDU BOE TVN UZQFT UP HFU BU UIFJS JOIBCJUBOUT 8JUI SF
TQFDU UP QSPEVDUT QBUUFSO NBUDIJOH HJWFT ZPV UIF NFBOT
GPS EFTUSVDUVSJOH BOE FYQPTJOH UIF DPOUFOUT PG QSPEVDUT
CJOEJOH POF PS NPSF WBMVFT DPOUBJOFE UIFSFJO UP OBNFT
8JUI TVNT QBUUFSO NBUDIJOH MFUT ZPV EJTDSJNJOBUF XIJDI
JOIBCJUBOU PG B TVN ZPV NFBO UP IBOEMF JO UIBU NBUDI
*UƊT CFTU UP FYQMBJO QBUUFSO NBUDIJOH JO UFSNT PG IPX
EBUBUZQFT XPSL TP XFƊSF HPJOH UP VTF UFSNJOPMPHZ UIBU
ZPV NBZ OPU GVMMZ VOEFSTUBOE ZFU 8FƊMM DPWFS UIJT NPSF
EFFQMZ TPPO

-- nullary data constructor, not a sum or product.


-- Just a single value.
data Blah = Blah

1BUUFSO NBUDIJOH PO Blah DBO POMZ EP POF UIJOH

blahFunc :: Blah -> Bool


blahFunc Blah = True
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

data Identity a =
Identity a
deriving (Eq, Show)

*EFOUJUZ JT B VOBSZ EBUB DPOTUSVDUPS 4UJMM OPU B QSPEVDU


POMZ DPOUBJOT POF WBMVF

-- when you pattern match on Identity


-- you can unpack and expose the 'a'

unpackIdentity :: Identity a -> a


unpackIdentity (Identity x) = x

-- But you can choose to ignore


-- the contents of Identity

ignoreIdentity :: Identity a -> Bool


ignoreIdentity (Identity _) = True

-- or ignore it completely since matching on


-- a non-sum data constructor changes nothing.

ignoreIdentity' :: Identity a -> Bool


ignoreIdentity' _ = True
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

data Product a b =
Product a b
deriving (Eq, Show)

/PX XF DBO DIPPTF UP VTF OPOF POF PS CPUI PG UIF WBMVFT


JO UIF QSPEVDU PG Ԑ BOE ԑ

productUnpackOnlyA :: Product a b -> a


productUnpackOnlyA (Product x _) = x

productUnpackOnlyB :: Product a b -> b


productUnpackOnlyB (Product _ y) = y

0S XF DBO CJOE UIFN CPUI UP B EJƵFSFOU OBNF

productUnpack :: Product a b -> (a, b)


productUnpack (Product x y) = (x, y)

8IBU IBQQFOT JG ZPV USZ UP CJOE UIF WBMVFT JO UIF QSPEVDU


UP UIF TBNF OBNF

data SumOfThree a b c =
FirstPossible a
| SecondPossible b
| ThirdPossible c
deriving (Eq, Show)
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

/PX XF DBO EJTDSJNJOBUF CZ UIF JOIBCJUBOUT PG UIF TVN


BOE DIPPTF UP EP EJƵFSFOU UIJOHT CBTFE PO XIJDI DPO
TUSVDUPS JO UIF TVN UIFZ XFSF

sumToInt :: SumOfThree a b c -> Integer


sumToInt (FirstPossible _) = 0
sumToInt (SecondPossible _) = 1
sumToInt (ThirdPossible _) = 2

-- We can selectively ignore inhabitants of the sum

sumToInt :: SumOfThree a b c -> Integer


sumToInt (FirstPossible _) = 0
sumToInt _ = 1

-- We still need to handle every possible value

1BUUFSO NBUDIJOH JT BCPVU ZPVS EBUB

 #PUUPN JT B OPOWBMVF VTFE UP EFOPUF UIBU UIF QSPHSBN


DBOOPU SFUVSO B WBMVF PS SFTVMU 5IF NPTU FMFNFOUBM
NBOJGFTUBUJPO PG UIJT JT B QSPHSBN UIBU MPPQT JOƶOJUFMZ
0UIFS GPSNT DBO JOWPMWF UIJOHT MJLF XSJUJOH B GVODUJPO
UIBU EPFTOƊU IBOEMF BMM PG JUT JOQVUT BOE GBJMT PO B QBUUFSO
NBUDI 5IF GPMMPXJOH BSF FYBNQMFT PG CPUUPN
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

-- If you apply this to any values,


-- it'll recurse indefinitely.
f x = f x

-- It'll a'splode if you pass a False value


dontDoThis :: Bool -> Int
dontDoThis True = 1

-- morally equivalent to

definitelyDontDoThis :: Bool -> Int


definitelyDontDoThis True = 1
definitelyDontDoThis False = error "oops"

-- don't use error. We'll show you a better way soon.

#PUUPN DBO CF VTFGVM BT B DBOBSZ GPS TJHOBMJOH XIFO DPEF


QBUIT BSF CFJOH FWBMVBUFE 8F VTVBMMZ EP UIJT UP EFUFSNJOF
IPX MB[Z B QSPHSBN JT PS JTOƊU :PVƊMM TFF B MPU PG UIJT JO
PVS DIBQUFS PO OPOTUSJDUOFTT MBUFS PO

 )JHIFSPSEFS GVODUJPOT BSF GVODUJPOT XIJDI UIFNTFMWFT UBLF


GVODUJPOT BT BSHVNFOUT PS SFUVSO GVODUJPOT BT SFTVMUT %VF
UP DVSSZJOH UFDIOJDBMMZ BOZ GVODUJPO UIBU BQQFBST UP UBLF
NPSF UIBO POF BSHVNFOU JT IJHIFS PSEFS JO )BTLFMM
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

-- Technically higher order


-- because of currying
Int -> Int -> Int

-- See? Returns another function


-- after applying the first argument
Int -> (Int -> Int)

-- The rest of the following examples are


-- types of higher order functions

(a -> b) -> a -> b

(a -> b) -> [a] -> [b]

(Int -> Bool) -> [Int] -> [Bool]

-- also higher order, this one


-- takes a function argument which itself
-- is higher order as well.

((a -> b) -> c) -> [a] -> [c]

 $PNQPTJUJPO JT UIF BQQMJDBUJPO PG B GVODUJPO UP UIF SFTVMU


PG IBWJOH BQQMJFE BOPUIFS GVODUJPO 5IF DPNQPTJUJPO PQ
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

FSBUPS JT B IJHIFSPSEFS GVODUJPO BT JU UBLFT UIF GVODUJPOT


JU DPNQPTFT BT BSHVNFOUT BOE UIFO SFUVSOT B GVODUJPO PG
UIF DPNQPTJUJPO

(.) :: (b -> c) -> (a -> b) -> a -> c

-- is actually

(.) :: (b -> c) -> (a -> b) -> (a -> c)

-- or

(.) :: (b -> c) -> ((a -> b) -> (a -> c))

-- can be implemented as
comp :: (b -> c) -> ((a -> b) -> (a -> c))
comp f g x = f (g x)

5IF GVODUJPO g JT BQQMJFE UP x f JT BQQMJFE UP UIF SFTVMU PG


g x

 1PJOUGSFF JT QSPHSBNNJOH UBDJUMZ PS XJUIPVU NFOUJPOJOH


BSHVNFOUT CZ OBNF 5IJT UFOET UP MPPL MJLF ƌQMVNCZƍ
DPEF XIFSF ZPVƊSF SPVUJOH EBUB BSPVOE JNQMJDJUMZ PS MFBW
JOH PƵ VOOFDFTTBSZ BSHVNFOUT UIBOLT UP DVSSZJOH 5IF
ƌQPJOUƍ SFGFSSFE UP JO UIF UFSN QPJOUGSFF JT BO BSHVNFOU
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

-- not pointfree
blah x = x
addAndDrop x y = x + 1
reverseMkTuple a b = (b, a)
reverseTuple (a, b) = (b, a)

-- pointfree versions of the above


blah = id
addAndDrop = const . (1 +)
reverseMkTuple = flip (,)
reverseTuple = uncurry (flip (,))

5P TFF NPSF FYBNQMFT MJLF UIJT DIFDL PVU UIF )BTLFMM 8JLJ
QBHF PO 1PJOUGSFF BU https://wiki.haskell.org/Pointfree

 'PMMPXVQ SFTPVSDFT


 1BVM )VEBL +PIO 1FUFSTPO +PTFQI 'BTFM " (FOUMF *O
USPEVDUJPO UP )BTLFMM DIBQUFS PO DBTF FYQSFTTJPOT BOE
QBUUFSO NBUDIJOH
https://www.haskell.org/tutorial/patterns.html

 4JNPO 1FZUPO +POFT 5IF *NQMFNFOUBUJPO PG 'VODUJPOBM


1SPHSBNNJOH -BOHVBHFT QBHFT 
http://research.microsoft.com/en-us/um/people/simonpj/papers/
slpj-book-1987/index.htm
$)"15&3  .03& '6/$5*0/"- 1"55&3/4 

 $ISJTUPQIFS 4USBDIFZ 'VOEBNFOUBM $PODFQUT JO 1SP


HSBNNJOH -BOHVBHFT QBHF  GPS FYQMBOBUJPO PG DVSSZ
JOH
http://www.cs.cmu.edu/~crary/819-f09/Strachey67.pdf

 +/ 0MJWFJSB "O JOUSPEVDUJPO UP QPJOUGSFF QSPHSBNNJOH


http://www.di.uminho.pt/~jno/ps/iscalc_1.ps.gz

 .BOVFM "MDJOP 1FSFJSB EB $VOIB 1PJOUGSFF 1SPHSBN


$BMDVMBUJPO
http://www4.di.uminho.pt/~mac/Publications/phd.pdf
$IBQUFS 

3FDVSTJPO

*NBHJOF B QPSUJPO PG UIF


UFSSJUPSZ PG &OHMBOE IBT
CFFO QFSGFDUMZ MFWFMMFE
BOE B DBSUPHSBQIFS USBDFT
B NBQ PG &OHMBOE 5IF
XPSL JT QFSGFDU 5IFSF JT
OP QBSUJDVMBS PG UIF
UFSSJUPSZ PG &OHMBOE
TNBMM BT JU DBO CF UIBU IBT
OPU CFFO SFDPSEFE JO UIF
NBQ &WFSZUIJOH IBT JUT
PXO DPSSFTQPOEFODF
5IF NBQ UIFO NVTU
DPOUBJO B NBQ PG UIF NBQ
UIBU NVTU DPOUBJO B NBQ
PG UIF NBQ PG UIF NBQ
BOE TP PO UP JOƶOJUZ

+PSHF -VJT #PSHFT DJUJOH


+PTJBI 3PZDF


$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

 3FDVSTJPO
3FDVSTJPO JT EFƶOJOH B GVODUJPO JO UFSNT PG JUTFMG WJB TFMG
SFGFSFOUJBM FYQSFTTJPOT *U NFBOT UIBU UIF GVODUJPO XJMM DPO
UJOVF UP DBMM JUTFMG BOE SFQFBU JUT CFIBWJPS VOUJM TPNF DPOEJUJPO
JT NFU UP SFUVSO B SFTVMU *UƊT BO JNQPSUBOU DPODFQU JO )BTLFMM
BOE JO NBUIFNBUJDT CFDBVTF JU HJWFT VT B NFBOT PG FYQSFTT
JOH JOEFƶOJUF PS JODSFNFOUBM DPNQVUBUJPO XJUIPVU GPSDJOH VT
UP FYQMJDJUMZ SFQFBU PVSTFMWFT BOE BMMPXJOH UIF EBUB XF BSF
QSPDFTTJOH UP EFDJEF XIFO XF BSF EPOF DPNQVUJOH
3FDVSTJPO JT B OBUVSBM QSPQFSUZ PG NBOZ MPHJDBM BOE NBUI
FNBUJDBM TZTUFNT JODMVEJOH IVNBO MBOHVBHF 5IBU UIFSF JT
OP MJNJU PO UIF OVNCFS PG FYQSFTTJCMF WBMJE TFOUFODFT JO IV
NBO MBOHVBHF JT EVF UP SFDVSTJPO " TFOUFODF JO &OHMJTI DBO
IBWF BOPUIFS TFOUFODF OFTUFE XJUIJO JU 4FOUFODFT DBO CF
SPVHIMZ EFTDSJCFE BT TUSVDUVSFT XIJDI IBWF B OPVO QISBTF B
WFSC QISBTF BOE PQUJPOBMMZ BOPUIFS TFOUFODF 5IJT QPTTJCJMJUZ
GPS VOMJNJUFE OFTUFE TFOUFODFT JT SFDVSTJWF BOE FOBCMFT UIF
MJNJUMFTT FYQSFTTJCJMJUZ UIFSFJO 3FDVSTJPO JT B NFBOT PG FY
QSFTTJOH DPEF UIBU NVTU UBLF BO JOEFƶOJUF OVNCFS PG TUFQT UP
SFUVSO B SFTVMU
#VU UIF MBNCEB DBMDVMVT EPFT OPU BQQFBS PO UIF TVSGBDF
UP IBWF BOZ NFBOT PG SFDVSTJPO CFDBVTF PG UIF BOPOZNJUZ
PG FYQSFTTJPOT )PX EP ZPV DBMM TPNFUIJOH XJUIPVU B OBNF
#FJOH BCMF UP XSJUF SFDVSTJWF GVODUJPOT UIPVHI JT FTTFOUJBM UP
5VSJOH DPNQMFUFOFTT 8F VTF B DPNCJOBUPS Ƈ LOPXO BT UIF
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

: DPNCJOBUPS PS ƶYFEQPJOU DPNCJOBUPS Ƈ UP XSJUF SFDVSTJWF


GVODUJPOT JO UIF MBNCEB DBMDVMVT )BTLFMM IBT OBUJWF SFDVSTJPO
BCJMJUZ CBTFE PO UIF TBNF QSJODJQMF BT UIF : DPNCJOBUPS
*U JT JNQPSUBOU UP IBWF B TPMJE VOEFSTUBOEJOH PG UIF CFIBWJPS
PG SFDVSTJWF GVODUJPOT *O MBUFS DIBQUFST XF XJMM TFF UIBU JO
GBDU JU JT OPU PǒFO OFDFTTBSZ UP XSJUF PVS PXO SFDVSTJWF GVOD
UJPOT BT NBOZ TUBOEBSE IJHIFSPSEFS GVODUJPOT IBWF CVJMUJO
SFDVSTJPO #VU XJUIPVU VOEFSTUBOEJOH UIF TZTUFNBUJD CFIBW
JPS PG SFDVSTJPO JUTFMG JU DBO CF EJƸDVMU UP SFBTPO BCPVU UIPTF
)0'T *O UIJT DIBQUFS XF XJMM

Ƒ FYQMPSF XIBU SFDVSTJPO JT BOE IPX SFDVSTJWF GVODUJPOT


FWBMVBUF

Ƒ HP TUFQCZTUFQ UISPVHI UIF QSPDFTT PG XSJUJOH SFDVSTJWF


GVODUJPOT

Ƒ IBWF GVO XJUI CPUUPN

 'BDUPSJBM
0OF PG UIF DMBTTJD JOUSPEVDUPSZ GVODUJPOT GPS EFNPOTUSBUJOH
SFDVSTJPO JO GVODUJPOBM MBOHVBHFT JT GBDUPSJBM *O BSJUINFUJD
ZPV NJHIUƊWF TFFO FYQSFTTJPOT MJLF 4! 5IF CBOH ZPVƊSF TFFJOH
OFYU UP UIF OVNCFS  JT UIF OPUBUJPO GPS UIF GBDUPSJBM GVODUJPO

-FUT FWBMVBUF 4!


$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

4! = 4 * 3 * 2 * 1
12 * 2 * 1
24 * 1
24
4! = 24

/PX MFUƊT EP JU UIF TJMMZ XBZ JO )BTLFMM

fourFactorial :: Integer
fourFactorial = 4 * 3 * 2 * 1

5IJT XJMM SFUVSO UIF DPSSFDU SFTVMU CVU JU POMZ DPWFST POF
QPTTJCMF SFTVMU GPS factorial 5IJT JT MFTT UIBO JEFBM 8F XBOU
UP FYQSFTT UIF HFOFSBM JEFB PG UIF GVODUJPO OPU FODPEF TQFDJƶD
JOQVUT BOE PVUQVUT NBOVBMMZ
/PX XFƊMM MPPL BU TPNF CSPLFO DPEF UP JOUSPEVDF UIF DPO
DFQU PG B CBTF DBTF
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

-- This won't work. It never stops.


brokenFact1 :: Integer -> Integer
brokenFact1 n = n * brokenFact1 (n - 1)

-- Let's apply this to 4


-- and see what happens
brokenFact1 4 = 4 * (4 - 1)
* ((4 - 1) - 1)
* (((4 - 1) - 1) - 1)
... this series never stops

5IF XBZ XF DBO TUPQ B SFDVSTJWF FYQSFTTJPO JT CZ IBWJOH B


CBTF DBTF UIBU TUPQT UIF TFMGBQQMJDBUJPO UP GVSUIFS BSHVNFOUT
6OEFSTUBOEJOH UIJT JT DSJUJDBM GPS XSJUJOH GVODUJPOT XIJDI BSF
DPSSFDU BOE UFSNJOBUF QSPQFSMZ )FSFƊT XIBU UIJT MPPLT MJLF GPS
factorial

module Factorial where

factorial :: Integer -> Integer


factorial 0 = 1
factorial n = n * factorial (n - 1)
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

brokenFact1 4 = 4 * (4 - 1)
* ((4 - 1) - 1)
* (((4 - 1) - 1) - 1)
* ((((4 - 1) - 1) - 1) - 1)
* (((((4 - 1) - 1) - 1) - 1) - 1)
... never stops

#VU UIF CBTF DBTF factorial 0 = 1 JO UIF ƶYFE WFSTJPO HJWFT


PVS GVODUJPO B TUPQQJOH QPJOU TP UIF SFEVDUJPO DIBOHFT
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

-- Changes to
-- n = n * factorial (n - 1)
factorial 4 = 4 * factorial (4 - 1)

-- evaluate (-) applied to 4 and 1


4 * factorial 3

-- evaluate factorial applied to 3


-- expands to 3 * factorial (3 - 1)
4 * 3 * factorial (3 - 1)

-- beta reduce (-) applied to 3 and 1


4 * 3 * factorial 2

-- evaluate factorial applied to 2


4 * 3 * 2 * factorial (2 - 1)

-- evaluate (-) applied to 2 and 1


4 * 3 * 2 * factorial 1

-- evaluate factorial applied to 1


4 * 3 * 2 * 1 * factorial (1 - 1)

-- evaluate (-) applied to 1 and 1


-- we know factorial 0 = 1
-- so we evaluate that to 1
4 * 3 * 2 * 1 * 1
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

.BLJOH PVS CBTF DBTF BO JEFOUJUZ WBMVF GPS UIF GVODUJPO


NVMUJQMJDBUJPO JO UIJT DBTF
NFBOT UIBU BQQMZJOH UIF GVODUJPO
UP UIBU DBTF EPFTOƊU DIBOHF UIF SFTVMU PG QSFWJPVT BQQMJDBUJPOT

"OPUIFS XBZ UP MPPL BU SFDVSTJPO


*O UIF MBTU DIBQUFS XF MPPLFE BU B IJHIFSPSEFS GVODUJPO DBMMFE
DPNQPTJUJPO 'VODUJPO DPNQPTJUJPO JT B XBZ PG UZJOH UXP PS
NPSF
GVODUJPOT UPHFUIFS TVDI UIBU UIF SFTVMU PG BQQMZJOH UIF
ƶSTU GVODUJPO HFUT QBTTFE BT BO BSHVNFOU UP UIF OFYU GVODUJPO
5IJT JT UIF TBNF UIJOH SFDVSTJWF GVODUJPOT BSF EPJOH ƈ UBLJOH
UIF SFTVMU PG UIF ƶSTU BQQMJDBUJPO PG UIF GVODUJPO BOE QBTTJOH JU
UP UIF OFYU GVODUJPO ƈ FYDFQU JO UIF DBTF PG SFDVSTJWF GVODUJPOT
UIF ƶSTU SFTVMU HFUT QBTTFE CBDL UP UIF TBNF GVODUJPO SBUIFS UIBO
B EJƵFSFOU POF VOUJM JU SFBDIFT UIF CBTF DBTF BOE UFSNJOBUFT
8IFSF GVODUJPO DPNQPTJUJPO BT XF OPSNBMMZ UIJOL PG JU JT
TUBUJD BOE EFƶOJUF SFDVSTJWF DPNQPTJUJPOT BSF JOEFƶOJUF 5IF
OVNCFS PG UJNFT UIF GVODUJPO NBZ CF BQQMJFE EFQFOET PO UIF
BSHVNFOUT UP UIF GVODUJPO BOE UIF BQQMJDBUJPOT DBO CF JOƶOJUF
JG B TUPQQJOH QPJOU JT OPU DMFBSMZ EFƶOFE
-FUƊT SFDBMM UIBU GVODUJPO DPNQPTJUJPO IBT UIF GPMMPXJOH
UZQF

(.) :: (b -> c) -> (a -> b) -> a -> c

"OE XIFO XF VTF JU MJLF UIJT


$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

take 5 . filter odd . enumFrom $ 3

XF LOPX UIBU UIF ƶSTU SFTVMU XJMM CF B MJTU HFOFSBUFE CZ


enumFrom XIJDI XJMM CF QBTTFE UP filter odd HJWJOH VT B MJTU PG
POMZ UIF PEE SFTVMUT BOE UIBU MJTU XJMM CF QBTTFE UP take 5 BOE
PVS ƶOBM SFTVMU XJMM CF UIF ƶSTU ƶWF NFNCFST PG UIBU MJTU 5IVT
SFTVMUT HFU QJQFE UISPVHI B TFSJFT PG GVODUJPOT
3FDVSTJPO JT TFMGSFGFSFOUJBM DPNQPTJUJPO 8F BQQMZ B GVOD
UJPO UP BO BSHVNFOU UIFO QBTT UIBU SFTVMU PO BT BO BSHVNFOU
UP B TFDPOE BQQMJDBUJPO PG UIF TBNF GVODUJPO BOE TP PO
/PX MPPL BHBJO BU IPX UIF DPNQPTF GVODUJPO (.) JT XSJUUFO

(.) :: (b -> c) -> (a -> b) -> a -> c


(.) f g = \x -> f (g x)

" QSPHSBNNJOH MBOHVBHF TVDI BT )BTLFMM UIBU JT CVJMU


QVSFMZ PO MBNCEB DBMDVMVT IBT POF WFSC GPS FYQSFTTJOH DPNQV
UBUJPOT UIBU DBO CF FWBMVBUFE BQQMZ 8F BQQMZ B GVODUJPO UP BO
BSHVNFOU "QQMZJOH B GVODUJPO UP BO BSHVNFOU BOE QPUFOUJBMMZ
EPJOH TPNFUIJOH XJUI UIF SFTVMU JT BMM XF DBO EP OP NBUUFS
XIBU TZOUBDUJD DPOWFOJFODFT XF DPOTUSVDU UP NBLF JU TFFN UIBU
XF BSF EPJOH NPSF UIBO UIBU 8IJMF XF HJWF GVODUJPO DPNQP
TJUJPO B TQFDJBM OBNF BOE PQFSBUPS UP QPJOU VQ UIF QBUUFSO BOE
NBLF JU DPOWFOJFOU UP VTF JUƊT POMZ B XBZ PG TBZJOH

Ƒ HJWFO UXP GVODUJPOT ԕ BOE Ԗ BT BSHVNFOUT UP (.)



.BOZ UIBOLT UP (FPSHF .BLSZEBLJT GPS EJTDVTTJOH UIJT XJUI VT
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

Ƒ XIFO XF HFU BO BSHVNFOU ԧ BQQMZ Ԗ UP ԧ

Ƒ UIFO BQQMZ ԕ UP UIF SFTVMU PG (g x) PS

Ƒ UP SFQISBTF JO DPEF

(.) f g = \x -> f (g x)

8JUI GVODUJPO SFDVSTJPO ZPV NJHIU OPUJDF UIBU JU JT GVOD


UJPO BQQMJDBUJPO JO UIF TBNF XBZ UIBU DPNQPTJUJPO JT 5IF
EJƵFSFODF JT UIBU JOTUFBE PG B ƶYFE OVNCFS PG BQQMJDBUJPOT
SFDVSTJWF GVODUJPOT SFMZ PO JOQVUT UP EFUFSNJOF XIFO UP TUPQ
BQQMZJOH GVODUJPOT UP TVDDFTTJWF SFTVMUT 8JUIPVU B TQFDJƶFE
TUPQQJOH QPJOU UIF SFTVMU PG (g x) XJMM LFFQ CFJOH QBTTFE CBDL
UP Ԗ JOEFƶOJUFMZ
-FUƊT MPPL BU TPNF DPEF UP TFF UIF TJNJMBSJUZ JO QBUUFSOT

inc :: Num a => a -> a


inc = (+1)

three = inc . inc . inc $ 0


-- different syntax, same thing
three' = (inc . inc . inc) 0

#FDBVTF )BTLFMM JT CVJMU PO QVSF MBNCEB DBMDVMVT SFDVSTJPO JT JNQMFNFOUFE JO UIF
MBOHVBHF UISPVHI UIF : PS ƶYFEQPJOU DPNCJOBUPS :PV DBO SFBE B WFSZ HPPE FYQMBOBUJPO
PG UIBU BU http://mvanier.livejournal.com/2897.html JG ZPV BSF JOUFSFTUFE JO LOPXJOH IPX JU
XPSLT
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

0VS DPNQPTJUJPO PG inc CBLFT UIF OVNCFS PG BQQMJDBUJPOT


JOUP UIF TPVSDF DPEF 8F EPOƊU QSFTFOUMZ IBWF B NFBOT PG
DIBOHJOH IPX NBOZ UJNFT XF XBOU JU UP BQQMZ inc XJUIPVU
XSJUJOH B OFX GVODUJPO
4P XF NJHIU XBOU UP NBLF B HFOFSBM GVODUJPO UIBU DBO BQQMZ
inc BO JOEFƶOJUF OVNCFS PG UJNFT BOE BMMPX VT UP TQFDJGZ BT
BO BSHVNFOU IPX NBOZ UJNFT JU TIPVME CF BQQMJFE

incTimes :: (Eq a, Num a) => a -> a -> a


incTimes 0 n = n
incTimes times n = 1 + (incTimes (times - 1) n)

)FSF ԣԘԜԔԢ JT B WBSJBCMF SFQSFTFOUJOH UIF OVNCFS PG UJNFT


UIF JODSFNFOUJOH GVODUJPO OPU DBMMFE inc IFSF CVU XSJUUFO BT 1
+ JO UIF GVODUJPO CPEZ
TIPVME CF BQQMJFE UP UIF BSHVNFOU ԝ
*G XF XBOU UP BQQMZ JU [FSP UJNFT JU XJMM KVTU SFUVSO PVS ԝ UP VT
0UIFSXJTF UIF JODSFNFOUJOH GVODUJPO XJMM CF BQQMJFE BT NBOZ
UJNFT BT XFƊWF EFDMBSFE

Prelude> incTimes 10 0
10
Prelude> incTimes 5 0
5
Prelude> incTimes 5 5
10

--does this look familiar?


$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

*O B GVODUJPO TVDI BT UIJT UIF MPPNJOH UISFBU PG VOFOEJOH


SFDVSTJPO JT NJOJNJ[FE CFDBVTF UIF OVNCFS PG UJNFT UP BQQMZ
UIF GVODUJPO JT BO BSHVNFOU UP UIF GVODUJPO JUTFMG BOE XFƊWF
EFƶOFE B TUPQQJOH QPJOU XIFO (times - 1) JT FRVBM UP [FSP JU
SFUVSOT ԝ BOE UIBUƊT BMM UIF BQQMJDBUJPOT XF HFU
8F DBO BCTUSBDU UIF SFDVSTJPO PVU PG incTimes UPP

applyTimes :: (Eq a, Num a) =>


a -> (b -> b) -> b -> b
applyTimes 0 f b = b
applyTimes n f b = f (applyTimes (n-1) f b)

incTimes' :: (Eq a, Num a) => a -> a -> a


incTimes' times n = applyTimes times (+1) n

8IFO XF EP XF DBO NBLF UIF DPNQPTJUJPO NPSF PCWJPVT


JO applyTimes

applyTimes :: (Eq a, Num a) =>


a -> (b -> b) -> b -> b
applyTimes 0 f b = b
applyTimes n f b = f . applyTimes (n-1) f $ b

8FƊSF SFDVSTJWFMZ DPNQPTJOH PVS GVODUJPO ԕ XJUI applyTimes


(n-1) f IPXFWFS NBOZ TVCUSBDUJPOT JU UBLFT UP HFU n UP 
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

*OUFSNJTTJPO &YFSDJTF
8SJUF PVU UIF FWBMVBUJPO PG UIF GPMMPXJOH *U NJHIU CF B MJUUMF
MFTT OPJTZ JG ZPV EP TP XJUI UIF GPSN UIBU EJEOƊU VTF (.)

applyTimes 5 (+1) 5

 #PUUPN
વ PS CPUUPN JT B UFSN VTFE JO )BTLFMM UP SFGFS UP DPNQVUBUJPOT
UIBU EP OPU TVDDFTTGVMMZ SFTVMU JO B WBMVF 5IF UXP NBJO WBSJ
FUJFT PG CPUUPN BSF DPNQVUBUJPOT UIBU GBJMFE XJUI BO FSSPS PS
UIPTF UIBU GBJMFE UP UFSNJOBUF *O MPHJD વ DPSSFTQPOET UP GBMTF
-FU VT FYBNJOF B GFX XBZT CZ XIJDI XF DBO IBWF CPUUPN JO
PVS QSPHSBNT

Prelude> let x = x in x
*** Exception: <<loop>>
Prelude>

)FSF ()$J EFUFDUFE UIBU let x = x in x XBT OFWFS HPJOH


UP SFUVSO BOE TIPSUDJSDVJUFE UIF OFWFSFOEJOH DPNQVUBUJPO
5IJT JT BO FYBNQMF PG CPUUPN CFDBVTF JU XBT OFWFS HPJOH UP
SFUVSO B SFTVMU /PUF UIBU JG ZPVƊSF VTJOH B 8JOEPXT DPNQVUFS
UIJT FYBNQMF NBZ KVTU GSFF[F ZPVS ()$J BOE OPU UISPX BO
FYDFQUJPO
/FYU MFUƊT EFƶOF B GVODUJPO UIBU XJMM SFUVSO BO FYDFQUJPO
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

f :: Bool -> Int


f True = error "blah"
f False = 0

"OE MFUƊT USZ UIBU PVU JO ()$J

Prelude> f False
0
Prelude> f True
*** Exception: blah

*O UIF ƶSTU DBTF XIFO XF FWBMVBUFE f False BOE HPU 0 UIBU


EJEOƊU SFTVMU JO B CPUUPN WBMVF #VU XIFO XF FWBMVBUFE f True
XF HPU BO FYDFQUJPO XIJDI JT B NFBOT PG FYQSFTTJOH UIBU B
DPNQVUBUJPO GBJMFE 8F HPU BO FYDFQUJPO CFDBVTF XF TQFDJƶFE
UIBU UIJT WBMVF TIPVME SFUVSO BO FSSPS #VU UIJT UPP JT BO
FYBNQMF PG CPUUPN
"OPUIFS FYBNQMF PG B CPUUPN XPVME CF B QBSUJBM GVODUJPO
-FUƊT DPOTJEFS B SFXSJUF PG UIF QSFWJPVT GVODUJPO

f :: Bool -> Int


f False = 0

5IJT IBT UIF TBNF UZQF BOE SFUVSOT UIF TBNF PVUQVU 8IBU
XFƊWF EPOF JT FMJEFE UIF f True = error "blah" DBTF GSPN UIF
GVODUJPO EFƶOJUJPO 5IJT JT OPU B TPMVUJPO UP UIF QSPCMFN XJUI
UIF QSFWJPVT GVODUJPO CVU JU XJMM HJWF VT B EJƵFSFOU FYDFQUJPO
8F DBO PCTFSWF UIJT GPS PVSTFMWFT JO ()$J
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

Prelude> let f :: Bool -> Int; f False = 0


Prelude> f False
0
Prelude> f True
*** Exception: 6:23-33:
Non-exhaustive patterns in function f

5IF error WBMVF JT TUJMM UIFSF CVU PVS MBOHVBHF JNQMFNFO


UBUJPO JT NBLJOH JU UIF GBMMCBDL DBTF CFDBVTF XF EJEOƊU XSJUF
B UPUBM GVODUJPO UIBU JT B GVODUJPO XIJDI IBOEMFT BMM PG JUT JO
QVUT #FDBVTF XF GBJMFE UP EFƶOF XBZT UP IBOEMF BMM QPUFOUJBM
JOQVUT GPS FYBNQMF UISPVHI BO ƌPUIFSXJTFƍ DBTF UIF QSFWJPVT
GVODUJPO XBT SFBMMZ

f :: Bool -> Int


f False = 0
f _ = error $ "*** Exception: "
++ "Non-exhaustive"
++ "patterns in function f"

" QBSUJBM GVODUJPO JT POF XIJDI EPFT OPU IBOEMF BMM PG JUT
JOQVUT " UPUBM GVODUJPO JT POF UIBU EPFT )PX EP XF NBLF PVS
ԕ JOUP B UPUBM GVODUJPO 0OF XBZ JT XJUI UIF VTF PG UIF EBUBUZQF
Maybe

data Maybe a = Nothing | Just a


$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

5IF Maybe EBUBUZQF DBO UBLF BO BSHVNFOU *O UIF ƶSTU DBTF


Nothing UIFSF JT OP BSHVNFOU UIJT JT PVS XBZ UP TBZ UIBU UIFSF
JT OP SFTVMU PS EBUB GSPN UIF GVODUJPO XJUIPVU IJUUJOH CPUUPN
5IF TFDPOE DBTF Just a UBLFT BO BSHVNFOU BOE BMMPXT VT UP
SFUVSO UIF EBUB XFƊSF XBOUJOH Maybe NBLFT BMM VTFT PG nil WBMVFT
BOE NPTU VTFT PG CPUUPN VOOFDFTTBSZ )FSFƊT IPX XFƊE VTF JU
XJUI ԕ

f :: Bool -> Maybe Int


f False = Just 0
f _ = Nothing

/PUF UIBU UIF UZQF BOE CPUI DBTFT BMM DIBOHF /PU POMZ EP
XF SFQMBDF UIF error XJUI UIF Nothing WBMVF GSPN Maybe CVU XF
BMTP IBWF UP XSBQ 0 JO UIF Just DPOTUSVDUPS GSPN Maybe *G XF
EPOƊU EP TP XFƊMM HFU B UZQF FSSPS XIFO XF USZ UP MPBE UIF DPEF
BT ZPV DBO TFF

f :: Bool -> Maybe Int


f False = 0
f _ = Nothing

Prelude> :l code/brokenMaybe1.hs
[1 of 1] Compiling Main

code/brokenMaybe1.hs:3:11:
No instance for (Num (Maybe Int)) arising from the literal ‘0’
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

In the expression: 0
In an equation for ‘f’: f False = 0

5IJT UZQF FSSPS JT CFDBVTF BT CFGPSF 0 IBT UIF UZQF Num a =>
a TP JUƊT USZJOH UP HFU BO JOTUBODF PG Num GPS Maybe Int 8F DBO
DMBSJGZ PVS JOUFOU B CJU

f :: Bool -> Maybe Int


f False = 0 :: Int
f _ = Nothing

"OE UIFO HFU B CFUUFS UZQF FSSPS JO UIF CBSHBJO

Prelude> :l code/brokenMaybe2.hs
[1 of 1] Compiling Main

code/brokenMaybe2.hs:3:11:
Couldn't match expected type
‘Maybe Int’ with actual type ‘Int’
In the expression: 0 :: Int
In an equation for ‘f’: f False = 0 :: Int

8FƊMM FYQMBJO Maybe JO NPSF EFUBJM B CJU MBUFS

 'JCPOBDDJ OVNCFST


"OPUIFS DMBTTJD EFNPOTUSBUJPO PG SFDVSTJPO JO GVODUJPOBM QSP
HSBNNJOH JT B GVODUJPO UIBU DBMDVMBUFT UIF ԝUI OVNCFS JO B
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

'JCPOBDDJ TFRVFODF 5IF 'JCPOBDDJ TFRVFODF JT B TFRVFODF


PG OVNCFST JO XIJDI FBDI OVNCFS JT UIF TVN PG UIF QSFWJPVT
UXP          BOE TP PO *UƊT BO JOEFƶOJUF
DPNQVUBUJPO UIBU SFMJFT PO BEEJOH UXP PG JUT PXO NFNCFST TP
JUƊT B QFSGFDU DBOEJEBUF GPS B SFDVSTJWF GVODUJPO 8FƊSF HPJOH UP
XBML UISPVHI UIF TUFQT PG IPX XF XPVME XSJUF TVDI B GVODUJPO
GPS PVSTFMWFT UP HFU B CFUUFS VOEFSTUBOEJOH PG UIF SFBTPOJOH
QSPDFTT

 $POTJEFS UIF UZQFT


5IF ƶSTU UIJOH XFƊMM DPOTJEFS JT UIF QPTTJCMF UZQF TJHOBUVSF
GPS PVS GVODUJPO 5IF 'JCPOBDDJ TFRVFODF POMZ JOWPMWFT
QPTJUJWF XIPMF OVNCFST 5IF BSHVNFOU UP PVS 'JCPOBDDJ
GVODUJPO JT HPJOH UP CF B QPTJUJWF XIPMF OVNCFS CFDBVTF
XFƊSF USZJOH UP SFUVSO UIF WBMVF UIBU JT UIF ԝUI NFNCFS PG
UIF 'JCPOBDDJ TFRVFODF 0VS SFTVMU XJMM BMTP CF B QPTJUJWF
XIPMF OVNCFS TJODF UIBUƊT XIBU 'JCPOBDDJ OVNCFST BSF
8F XPVME CF MPPLJOH UIFO GPS WBMVFT UIBU BSF PG UIF Int PS
Integer UZQFT 8F DPVME VTF POF PG UIPTF DPODSFUF UZQFT
PS VTF B UZQFDMBTT GPS DPOTUSBJOFE QPMZNPSQIJTN 4QFDJG
JDBMMZ XF XBOU B UZQF TJHOBUVSF UIBU UBLFT POF JOUFHSBM
BSHVNFOU BOE SFUVSOT POF JOUFHSBM SFTVMU 4P PVS UZQF
TJHOBUVSF XJMM MPPL TPNFUIJOH MJLF UIJT
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

fibonacci :: Integer -> Integer


-- or
fibonacci :: Integral a => a -> a

 $POTJEFS UIF CBTF DBTF


*U NBZ TPNFUJNFT CF EJƸDVMU UP EFUFSNJOF ZPVS CBTF DBTF
VQ GSPOU CVU JUƊT XPSUI UIJOLJOH BCPVU 'PS POF UIJOH
ZPV EP XBOU UP FOTVSF UIBU ZPVS GVODUJPO XJMM UFSNJOBUF
'PS BOPUIFS UIJOH HJWJOH TFSJPVT DPOTJEFSBUJPO UP ZPVS
CBTF DBTF JT B WBMVBCMF QBSU PG VOEFSTUBOEJOH IPX ZPVS
GVODUJPO XPSLT 'JCPOBDDJ OVNCFST BSF QPTJUJWF JOUFHFST
TP B SFBTPOBCMF CBTF DBTF JT [FSP 8IFO UIF SFDVSTJWF
QSPDFTT IJUT [FSP JU TIPVME UFSNJOBUF
5IF 'JCPOBDDJ TFRVFODF JT BDUVBMMZ B CJU USJDLJFS UIBO TPNF
UIPVHI CFDBVTF JU SFBMMZ OFFET UXP CBTF DBTFT 5IF TF
RVFODF IBT UP TUBSU PƵ XJUI UXP OVNCFST TJODF UXP OVN
CFST BSF JOWPMWFE JO DPNQVUJOH UIF OFYU 5IF OFYU OVN
CFS BǒFS [FSP JT  BOE XF BEE [FSP UP  UP TUBSU UIF TFRVFODF
TP UIPTF XJMM CF PVS CBTF DBTFT

fibonacci :: Integral a => a -> a


fibonacci 0 = 0
fibonacci 1 = 1

 $POTJEFS UIF BSHVNFOUT


$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

8FƊWF BMSFBEZ EFUFSNJOFE UIBU UIF BSHVNFOU UP PVS GVOD


UJPO UIF WBMVF UP XIJDI UIF GVODUJPO JT BQQMJFE JT BO JOUF
HSBM OVNCFS BOE SFQSFTFOUT UIF NFNCFS PG UIF TFRVFODF
XF XBOU UP CF FWBMVBUFE 5IBU JT XF XBOU UP QBTT B WBMVF
TVDI BT  UP UIJT GVODUJPO BOE IBWF JU DBMDVMBUF UIF UI
OVNCFS JO UIF 'JCPOBDDJ TFRVFODF 8F POMZ OFFE UP IBWF
POF WBSJBCMF BT BO BSHVNFOU UP UIJT GVODUJPO UIFO
#VU UIBU BSHVNFOU XJMM BMTP CF VTFE BT BSHVNFOUT XJUIJO
UIF GVODUJPO EVF UP UIF SFDVSTJWF QSPDFTT &WFSZ 'JCPOBDDJ
OVNCFS JT UIF SFTVMU PG BEEJOH UIF QSFDFEJOH UXP OVNCFST
4P JO BEEJUJPO UP B WBSJBCMF ԧ XF XJMM OFFE UP VTF (x - 1)
BOE (x - 2) UP HFU CPUI UIF OVNCFST CFGPSF PVS BSHVNFOU

fibonacci :: Integral a => a -> a


fibonacci 0 = 0
fibonacci 1 = 1
fibonacci x = (x - 1) (x - 2)
-- note: this doesn't work yet.

 $POTJEFS UIF SFDVSTJPO


"MM SJHIU OPX XF DPNF UP UIF IFBSU PG UIF NBUUFS *O XIBU
XBZ XJMM UIJT GVODUJPO SFGFS UP JUTFMG BOE DBMM JUTFMG -PPL BU
XIBU XFƊWF XPSLFE PVU TP GBS XIBU OFFET UP IBQQFO OFYU
UP QSPEVDF B 'JCPOBDDJ OVNCFS 0OF UIJOH UIBU OFFET
UP IBQQFO JT UIBU (x - 1) BOE (x - 2) OFFE UP CF BEEFE
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

UPHFUIFS UP QSPEVDF B SFTVMU 5SZ TJNQMZ BEEJOH UIPTF UXP


UPHFUIFS BOE SVOOJOH UIF GVODUJPO UIBU XBZ

fibonacci :: Integral a => a -> a


fibonacci 0 = 0
fibonacci 1 = 1
fibonacci x = (x - 1) + (x - 2)

*G ZPV QBTT UIF WBMVF  UP UIBU GVODUJPO XIBU XJMM IBQQFO

*Main> fibonacci 6
9

8IZ #FDBVTF   
  

FRVBMT  #VU UIJT JTOƊU IPX


XF DBMDVMBUF 'JCPOBDDJ OVNCFST 5IF TJYUI NFNCFS PG
UIF 'JCPOBDDJ TFRVFODF JT OPU   
  

 8IBU XF
SFBMMZ XBOU JT UP BEE UIF ƶǒI NFNCFS PG UIF 'JCPOBDDJ
TFRVFODF UP UIF GPVSUI NFNCFS 5IBU SFTVMU XJMM CF UIF
TJYUI NFNCFS PG UIF TFRVFODF 8F EP UIJT CZ NBLJOH UIF
GVODUJPO SFGFS UP JUTFMG *O UIJT DBTF XF IBWF UP TQFDJGZ
UIBU CPUI (x - 1) BOE (x - 2) BSF UIFNTFMWFT 'JCPOBDDJ
OVNCFST TP XF IBWF UP DBMM UIF GVODUJPO UP JUTFMG UXJDF

fibonacci :: Integral a => a -> a


fibonacci 0 = 0
fibonacci 1 = 1
fibonacci x = fibonacci (x - 1) + fibonacci (x - 2)
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

/PX JG XF BQQMZ UIJT GVODUJPO UP UIF WBMVF  XF XJMM HFU B


EJƵFSFOU SFTVMU

*Main> fibonacci 6
8

8IZ #FDBVTF JU FWBMVBUFT UIJT SFDVSTJWFMZ

fibonacci 6 = fibonacci 5 + fibonacci 4

fibonacci 5 = fibonacci 4 + fibonacci 3

fibonacci 4 = fibonacci 3 + fibonacci 2

fibonacci 3 = fibonacci 2 + fibonacci 1

fibonacci 2 = fibonacci 1 + fibonacci 0

;FSP BOE  IBWF CFFO EFƶOFE BT CFJOH FRVBM UP [FSP BOE


 4P IFSF PVS SFDVSTJPO TUPQT BOE JU TUBSUT BEEJOH UIF
SFTVMU

fibonacci 0 + 0
fibonacci 1 + 1
fibonacci 2 + (1 + 0 =) 1
fibonacci 3 + (1 + 1 =) 2
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

fibonacci 4 + (1 + 2 =) 3
fibonacci 5 = (2 + 3 =) 5
fibonacci 6 = (3 + 5 =) 8

*U DBO CF EBVOUJOH BU ƶSTU UP UIJOL IPX ZPV XPVME XSJUF B


SFDVSTJWF GVODUJPO BOE XIBU JU NFBOT GPS B GVODUJPO UP DBMM
JUTFMG #VU BT ZPV DBO TFF JUƊT VTFGVM XIFO UIF GVODUJPO XJMM
NBLF SFGFSFODF UP JUT PXO SFTVMUT JO B SFQFBUFE GBTIJPO

 *OUFHSBM EJWJTJPO GSPN TDSBUDI


.BOZ QFPQMF MFBSOFE NVMUJQMJDBUJPO CZ NFNPSJ[JOH NVMUJ
QMJDBUJPO UBCMFT VTVBMMZ VQ UP Y PS Y EP[FO
 *O GBDU
POF DBO QFSGPSN NVMUJQMJDBUJPO JO UFSNT PG BEEJUJPO SFQFBUFE
PWFS BOE PWFS 4JNJMBSMZ POF DBO EFƶOF JOUFHSBM EJWJTJPO JO
UFSNT PG TVCUSBDUJPO
-FUƊT UIJOL UISPVHI PVS SFDVSTJWF EJWJTJPO GVODUJPO POF TUFQ
BU B UJNF 'JSTU MFUƊT DPOTJEFS UIF UZQFT XF XPVME XBOU UP VTF GPS
TVDI B GVODUJPO BOE TFF JG XF DBO DPOTUSVDU B SFBTPOBCMF UZQF
TJHOBUVSF 8IFO XF EJWJEF OVNCFST XF IBWF B OVNFSBUPS BOE
B EFOPNJOBUPS 8IFO XF FWBMVBUF 10 / 5 UP HFU UIF BOTXFS 
 JT UIF OVNFSBUPS  UIF EFOPNJOBUPS BOE  XBT UIF RVPUJFOU
4P XF IBWF BU MFBTU UISFF OVNCFST IFSF 4P QFSIBQT B UZQF
MJLF Integer -> Integer -> Integer XPVME CF TVJUBCMF :PV DPVME
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

FWFO BEE TPNF UZQF TZOPOZNT UIBU XPOƊU DIBOHF ZPVS DPEF

UP NBLF JU NPSF PCWJPVT JG ZPV XJTIFE

dividedBy :: Integer -> Integer -> Integer


dividedBy = div

-- changes to

type Numerator = Integer


type Denominator = Integer
type Quotient = Integer

dividedBy :: Numerator -> Denominator -> Quotient


dividedBy = div

'PS UIJT FYBNQMF XF EJEOƊU XSJUF PVU UIF SFDVSTJWF JNQMF


NFOUBUJPO PG dividedBy XF IBE JO NJOE "T JU UVSOT PVU XIFO
XF XSJUF UIF GVODUJPO XF XJMM XBOU UP DIBOHF UIF ƶOBM UZQF TJH
OBUVSF B CJU GPS SFBTPOT XFƊMM TFF JO B NJOVUF 4PNFUJNFT UIF
VTF PG UZQF TZOPOZNT DBO JNQSPWF UIF DMBSJUZ BOE QVSQPTF PG
ZPVS UZQF TJHOBUVSFT TP UIJT JT TPNFUIJOH ZPVƊMM TFF FTQFDJBMMZ
JO NPSF DPNQMFY DPEF 'PS PVS SFMBUJWFMZ TJNQMF GVODUJPO JU
NBZ OPU CF OFDFTTBSZ
/FYU MFUƊT UIJOL UISPVHI PVS CBTF DBTF 5IF XBZ XF EJWJEF JO
UFSNT PG TVCUSBDUJPO JT CZ TUPQQJOH XIFO PVS SFTVMU PG IBWJOH
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

TVCUSBDUFE SFQFBUFEMZ JT MPXFS UIBO UIF EJWJTPS *G JU EJWJEFT


FWFOMZ JUƊMM TUPQ BU 

Solve 20 divided by 4
-- [1] [2]
-- [1]: Dividend or numerator
-- [2]: Divisor or denominator
-- Result is quotient

20 divided by 4 == 20 - 4, 16
- 4, 12
- 4, 8
- 4, 4
- 4, 0
-- 0 is less than 4, so we stopped.
-- We subtracted 5 times, so 20 / 4 == 5

0UIFSXJTF XFƊMM IBWF B SFNBJOEFS -FUƊT MPPL BU B DBTF XIFSF


JU EPFTOƊU EJWJEF FWFOMZ

Solve 25 divided by 4

25 divided by 4 == 25 - 4, 21
- 4, 17
- 4, 13
- 4, 9
- 4, 5
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

- 4, 1
-- we stop at 1, because it's less than 4

*O UIF DBTF PG  EJWJEFE CZ  XF TVCUSBDUFE  TJY UJNFT BOE


IBE  BT PVS SFNBJOEFS 8F DBO HFOFSBMJ[F UIJT QSPDFTT PG EJ
WJEJOH XIPMF OVNCFST SFUVSOJOH UIF RVPUJFOU BOE SFNBJOEFS
JOUP B SFDVSTJWF GVODUJPO XIJDI EPFT UIF SFQFBUFE TVCUSBDUJPO
BOE DPVOUJOH GPS VT 4JODF XFƊE MJLF UP SFUVSO UIF RVPUJFOU
BOE UIF SFNBJOEFS XFƊSF HPJOH UP SFUVSO UIF UVQMF (,) BT UIF
SFTVMU PG PVS SFDVSTJWF GVODUJPO

dividedBy :: Integral a => a -> a -> (a, a)


dividedBy num denom = go num denom 0
where go n d count
| n < d = (count, n)
| otherwise = go (n - d) d (count + 1)

8FƊWF DIBOHFE UIF UZQF TJHOBUVSF GSPN UIF POF XF IBE


PSJHJOBMMZ XPSLFE PVU CPUI UP NBLF JU NPSF QPMZNPSQIJD
Integral a => a WFSTVT Integer
BOE BMTP UP SFUVSO UIF UVQMF
JOTUFBE PG KVTU BO JOUFHFS
)FSF XF VTFE B DPNNPO )BTLFMM JEJPN DBMMFE B go GVODUJPO
5IJT BMMPXT VT UP EFƶOF B GVODUJPO WJB B whereDMBVTF UIBU DBO
BDDFQU NPSF BSHVNFOUT UIBO UIF UPQMFWFM GVODUJPO dividedBy
EPFT *O UIJT DBTF UIF UPQMFWFM GVODUJPO UBLFT UXP BSHVNFOUT
num BOE denom CVU XF OFFE B UIJSE BSHVNFOU JO PSEFS UP LFFQ
USBDL PG IPX NBOZ UJNFT XF EP UIF TVCUSBDUJPO 5IBU BSHVNFOU
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

JT DBMMFE count BOE JT EFƶOFE XJUI B TUBSUJOH WBMVF PG [FSP BOE


JT JODSFNFOUFE CZ  FWFSZ UJNF UIF otherwise DBTF JT JOWPLFE
5IFSF BSF UXP CSBODIFT JO PVS go GVODUJPO 5IF ƶSTU DBTF
JT UIF NPTU TQFDJƶD XIFO UIF OVNFSBUPS ԝ JT MFTT UIBO UIF
EFOPNJOBUPS ԓ UIF SFDVSTJPO TUPQT BOE SFUVSOT B SFTVMU *U
JT OPU TJHOJƶDBOU UIBU XF DIBOHFE UIF BSHVNFOU OBNFT GSPN
ԝԤԜ BOE ԓԔԝԞԜ UP ԝ BOE ԓ 5IF go GVODUJPO IBT BMSFBEZ CFFO
BQQMJFE UP UIPTF BSHVNFOUT JO UIF EFƶOJUJPO PG dividedBy TP
UIF ԝԤԜ ԓԔԝԞԜ BOE  BSF CPVOE UP ԝ ԓ BOE ԒԞԤԝԣ JO UIF where
DMBVTF
5IF SFTVMU JT B UVQMF PG ԒԞԤԝԣ BOE UIF MBTU WBMVF GPS ԝ 5IJT JT
PVS CBTF DBTF UIBU TUPQT UIF SFDVSTJPO BOE HJWFT B ƶOBM SFTVMU
)FSFƊT BO FYBNQMF PG IPX dividedBy FYQBOET CVU XJUI UIF
DPEF JOMJOFE

dividedBy 10 2

-- first we'll do this the previous way,


-- but we'll keep track of how many times we subtracted.
10 divided by 2 == 10 - 2, 8 (subtracted 1 time)
- 2, 6 (subtracted 2 times)
- 2, 4 (subtracted 3 times)
- 2, 2 (subtracted 4 times)
- 2, 0 (subtracted 5 times)

4JODF UIF ƶOBM OVNCFS XBT  UIFSFƊT OP SFNBJOEFS 8F


$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

TVCUSBDUFE ƶWF UJNFT 4P 10 / 2 == 5


/PX XFƊMM FYQBOE UIF DPEF
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

dividedBy 10 2 =
go 10 2 0

| 10 < 2 = ...
-- false, skip this branch

| otherwise = go (10 - 2) 2 (0 + 1)
-- otherwise is literally the value True
-- so if first branch fails, this always succeeds

go 8 2 1
-- 8 isn't < 2, so the otherwise branch
go (8 - 2) 2 (1 + 1)
-- n == 6, d == 2, count == 2

go 6 2 2
go (6 - 2) 2 (2 + 1)
-- 6 isn't < 2, so the otherwise branch
-- n == 4, d == 2, count == 3

go 4 2 3
go (4 - 2) 2 (3 + 1)
-- 4 isn't < 2, so the otherwise branch
-- n == 2, d == 2, count == 4

go 2 2 4
go (2 - 2) 2 (4 + 1)
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

5IF SFTVMU PG ԒԞԤԝԣ JT UIF RVPUJFOU UIBU JT IPX NBOZ UJNFT


ZPV DBO TVCUSBDU  GSPN  *O B DBTF XIFSF UIFSF XBT B SFNBJO
EFS UIBU OVNCFS XPVME CF UIF ƶOBM WBMVF GPS ZPVS OVNFSBUPS
BOE XPVME CF SFUVSOFE BT UIF SFNBJOEFS

 $IBQUFS &YFSDJTFT


3FWJFX PG UZQFT
 8IBU JT UIF UZQF PG [[True, False], [True, True], [False,
True]]

B
Bool
C
NPTUMZ True
D
[a]
E
[[Bool]]

 8IJDI PG UIF GPMMPXJOH IBT UIF TBNF UZQF BT [[True, False],


[True, True], [False, True]]

B
[(True, False), (True, True), (False, True)]
C
[[3 == 3], [6 > 5], [3 < 4]]
D
[3 == 3, 6 > 5, 3 < 4]
E
["Bool", "more Bool", "Booly Bool!"]

 'PS UIF GPMMPXJOH GVODUJPO


$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

func :: [a] -> [a] -> [a]


func x y = x ++ y

XIJDI PG UIF GPMMPXJOH JT USVF

B
x BOE y NVTU CF PG UIF TBNF UZQF
C
x BOE y NVTU CPUI CF MJTUT
D
JG x JT B String UIFO y NVTU CF B String
E
BMM PG UIF BCPWF

 'PS UIF func DPEF BCPWF XIJDI JT B WBMJE BQQMJDBUJPO PG


func UP CPUI PG JUT BSHVNFOUT

B
func "Hello World"
C
func "Hello" "World"
D
func [1, 2, 3] "a, b, c"
E
func ["Hello", "World"]

3FWJFXJOH DVSSZJOH
(JWFO UIF GPMMPXJOH EFƶOJUJPOT UFMM VT XIBU WBMVF SFTVMUT GSPN
GVSUIFS BQQMJDBUJPOT
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

cattyConny :: String -> String -> String


cattyConny x y = x ++ " mrow " ++ y

-- fill in the types

flippy = flip cattyConny

appedCatty = cattyConny "woops"


frappe = flippy "haha"

 8IBU JT UIF WBMVF PG appedCatty "woohoo!" 5SZ UP EFUFS


NJOF UIF BOTXFS GPS ZPVSTFMG UIFO UFTU JO UIF 3&1-

 frappe "1"

 frappe (appedCatty "2")

 appedCatty (frappe "blue")

 cattyConny (frappe "pink")


(cattyConny "green" (appedCatty "blue"))

 cattyConny (flippy "Pugs" "are") "awesome"

3FDVSTJPO
 8SJUF PVU UIF TUFQT GPS SFEVDJOH dividedBy 15 2 UP JUT ƶOBM
BOTXFS BDDPSEJOH UP UIF )BTLFMM DPEF
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

 8SJUF B GVODUJPO UIBU SFDVSTJWFMZ TVNT BMM OVNCFST GSPN


 UP O O CFJOH UIF BSHVNFOU 4P UIBU JG O XBT  ZPVƊE BEE
     UP HFU  5IF UZQF TIPVME CF (Eq a, Num a)
=> a -> a

 8SJUF B GVODUJPO UIBU NVMUJQMJFT UXP JOUFHSBM OVNCFST


VTJOH SFDVSTJWF TVNNBUJPO 5IF UZQF TIPVME CF (Integral
a) => a -> a -> a

'JYJOH EJWJEFE#Z
0VS EJWJEFE#Z GVODUJPO XBTOƊU RVJUF JEFBM 'PS POF UIJOH *U
XBT B QBSUJBM GVODUJPO BOE EPFTOƊU SFUVSO B SFTVMU CPUUPN

XIFO HJWFO B EJWJTPS UIBU JT  PS MFTT


6TJOH UIF QSFFYJTUJOH div GVODUJPO XF DBO TFF IPX OFHBUJWF
OVNCFST TIPVME CF IBOEMFE

Prelude> div 10 2
5
Prelude> div 10 (-2)
-5
Prelude> div (-10) (-2)
5
Prelude> div (-10) (2)
-5

5IF OFYU JTTVF JT IPX UP IBOEMF [FSP ;FSP JT VOEFƶOFE


GPS EJWJTJPO JO NBUI TP SFBMMZ XF PVHIU UP VTF B EBUBUZQF UIBU
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

MFUT VT TBZ UIFSF XBT OP TFOTJCMF SFTVMU XIFO UIF VTFS EJWJEFT
CZ [FSP *G ZPV OFFE JOTQJSBUJPO DPOTJEFS VTJOH UIF GPMMPXJOH
EBUBUZQF UP IBOEMF UIJT

data DividedResult =
Result Integer
| DividedByZero

.D$BSUIZ  GVODUJPO
8FƊSF HPJOH UP EFTDSJCF B GVODUJPO JO &OHMJTI UIFO JO NBUI
OPUBUJPO UIFO TIPX ZPV XIBU ZPVS GVODUJPO TIPVME SFUVSO GPS
TPNF UFTU JOQVUT :PVS UBTL JT UP XSJUF UIF GVODUJPO JO )BTLFMM
5IF .D$BSUIZ  GVODUJPO ZJFMET ԧ ਷  XIFO ԧ   BOE 
PUIFSXJTF 5IF GVODUJPO JT SFDVSTJWF


৖ԝ ਷  JG ԝ  
Ԃ Ӹ ԝ
 ৗ

৕Ԃ Ӹ Ԃ Ӹ ԝ 

JG ԝ ମ 

mc91 = undefined

:PV IBWFOƊU TFFO map ZFU CVU BMM ZPV OFFE UP LOPX SJHIU
OPX JT UIBU JU BQQMJFT B GVODUJPO UP FBDI NFNCFS PG B MJTU BOE
SFUVSOT UIF SFTVMUJOH MJTU *UƊMM CF FYQMBJOFE JO NPSF EFUBJM JO
UIF OFYU DIBQUFS

Prelude> map mc91 [95..110]


[91,91,91,91,91,91,91,92,93,94,95,96,97,98,99,100]
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

/VNCFST JOUP XPSET


module WordNumber where

import Data.List (intersperse)

digitToWord :: Int -> String


digitToWord n = undefined

digits :: Int -> [Int]


digits n = undefined

wordNumber :: Int -> String


wordNumber n = undefined

)FSF undefined JT B QMBDFIPMEFS UP TIPX ZPV XIFSF ZPV OFFE


UP ƶMM JO UIF GVODUJPOT 5IF n UP UIF SJHIU PG UIF GVODUJPO OBNFT
JT UIF BSHVNFOU XIJDI XJMM CF BO JOUFHFS
'JMM JO UIF JNQMFNFOUBUJPOT PG UIF GVODUJPOT BCPWF TP UIBU
wordNumber SFUVSOT UIF &OHMJTI XPSE WFSTJPO PG UIF *OU WBMVF
:PV XJMM ƶSTU XSJUF B GVODUJPO UIBU UVSOT JOUFHFST GSPN  JOUP
UIFJS DPSSFTQPOEJOH &OHMJTI XPSET ƍPOF ƍ ƍUXP ƍ BOE TP PO
5IFO ZPV XJMM XSJUF B GVODUJPO UIBU UBLFT UIF JOUFHFS TFQBSBUFT
UIF EJHJUT BOE SFUVSOT JU BT B MJTU PG JOUFHFST 'JOBMMZ ZPV XJMM
OFFE UP BQQMZ UIF ƶSTU GVODUJPO UP UIF MJTU QSPEVDFE CZ UIF TFD
POE GVODUJPO BOE UVSO JU JOUP B TJOHMF TUSJOH XJUI JOUFSTQFSTFE
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

IZQIFOT
8FƊWF MBJE PVU NVMUJQMF GVODUJPOT GPS ZPV UP DPOTJEFS BT ZPV
UBDLMF UIF QSPCMFN :PV NBZ OPU OFFE BMM PG UIFN EFQFOEJOH
PO IPX ZPV TPMWF JUƇUIFTF BSF KVTU TVHHFTUJPOT 1MBZ XJUI
UIFN BOE MPPL VQ UIFJS EPDVNFOUBUJPO UP VOEFSTUBOE UIFN
JO EFFQFS EFUBJM
:PV XJMM QSPCBCMZ ƶOE UIJT EJƸDVMU

div :: Integral a => a -> a -> a


mod :: Integral a => a -> a -> a
map :: (a -> b) -> [a] -> [b]
concat :: [[a]] -> [a]
intersperse :: a -> [a] -> [a]
(++) :: [a] -> [a] -> [a]
(:[]) :: a -> [a]

"MTP DPOTJEFS

Prelude> div 135 10


13
Prelude> mod 135 10
5
Prelude> div 13 10
1
Prelude> mod 13 10
3
$)"15&3  '6/$5*0/4 5)"5 $"-- 5)&.4&-7&4 

)FSF JT XIBU ZPVS PVUQVU TIPVME MPPL JO UIF 3&1- XIFO JUƊT
XPSLJOH

Prelude> wordNumber 12324546


"one-two-three-two-four-five-four-six"
Prelude>

 %FƶOJUJPOT
 3FDVSTJPO JT B NFBOT PG DPNQVUJOH SFTVMUT UIBU NBZ SFRVJSF
BO JOEFƶOJUF BNPVOU PG XPSL UP PCUBJO UISPVHI UIF VTF PG
SFQFBUFE GVODUJPO BQQMJDBUJPO .PTU SFDVSTJWF GVODUJPOT
UIBU UFSNJOBUF PS PUIFSXJTF EP VTFGVM XPSL XJMM PǒFO IBWF
B DBTF UIBU DBMMT JUTFMG BOE B CBTF DBTF UIBU BDUT BT B CBDLTUPQ
PG TPSUT GPS UIF SFDVSTJPO

-- not recursive
lessOne :: Int -> Int
lessOne n = n - 1

-- recursive
zero :: Int -> Int
zero 0 = 0
zero n = zero (n - 1)
$IBQUFS 

-JTUT

*G UIF EPPST PG QFSDFQUJPO


XFSF DMFBOTFE FWFSZUIJOH
XPVME BQQFBS UP NBO BT JU
JT  JOƶOJUF

8JMMJBN #MBLF


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 -JTUT
-JTUT EP EPVCMF EVUZ JO )BTLFMM 5IF ƶSTU QVSQPTF MJTUT TFSWF
JT BT B XBZ UP SFGFS UP BOE QSPDFTT B DPMMFDUJPO PS QMVSBMJUZ PG
WBMVFT 5IF TFDPOE JT BT BO JOƶOJUF TFSJFT PG WBMVFT VTVBMMZ
HFOFSBUFE CZ B GVODUJPO XIJDI BMMPXT UIFN UP BDU BT B TUSFBN
EBUBUZQF
*O UIJT DIBQUFS XF XJMM

Ƒ FYQMBJO MJTUƊT EBUBUZQF BOE IPX UP QBUUFSO NBUDI PO MJTUT

Ƒ QSBDUJDF NBOZ TUBOEBSE MJCSBSZ GVODUJPOT GPS PQFSBUJOH


PO MJTUT

Ƒ MFBSO BCPVU UIF VOEFSMZJOH SFQSFTFOUBUJPOT PG MJTUT

Ƒ TFF XIBU UIBU SFQSFTFOUBUJPO NFBOT GPS UIFJS FWBMVBUJPO

Ƒ BOE EP B XIPMF CVODI PG FYFSDJTFT

 5IF MJTU EBUBUZQF


5IF MJTU EBUBUZQF JO )BTLFMM JT EFƶOFE MJLF UIJT

data [] a = [] | a : [a]

)FSF [] JT UIF UZQF DPOTUSVDUPS GPS MJTUT BT XFMM BT UIF EBUB


DPOTUSVDUPS GPS UIF FNQUZ MJTU 5IF [] EBUB DPOTUSVDUPS JT B
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

OVMMBSZ DPOTUSVDUPS CFDBVTF JU UBLFT OP BSHVNFOUT 5IF TFDPOE


EBUB DPOTUSVDUPS JO DPOUSBTU IBT BSHVNFOUT (:) JT BO JOƶY
PQFSBUPS VTVBMMZ DBMMFE ƉDPOTƊ TIPSU GPS DPOTUSVDU
 )FSF DPOT
UBLFT B WBMVF PG UZQF a BOE B MJTU PG UZQF [a] BOE FWBMVBUFT UP
[a]
8IFSFBT UIF MJTU EBUBUZQF BT B XIPMF JT B TVN UZQF BT XF DBO
UFMM GSPN UIF | JO UIF EFƶOJUJPO UIF TFDPOE EBUB DPOTUSVDUPS (:)
`cons` JT B QSPEVDU CFDBVTF JU UBLFT UXP BSHVNFOUT 3FNFNCFS
B TVN UZQF DBO CF SFBE BT BO ƌPSƍ BT JO UIF Bool EBUBUZQF XIFSF
ZPV HFU False PS True " QSPEVDU JT MJLF BO ƌBOEƍ 8FƊSF HPJOH
UP UBML NPSF BCPVU TVN BOE QSPEVDU UZQFT JO BOPUIFS DIBQUFS
CVU GPS OPX JU XJMM TVƸDF UP SFDPHOJ[F UIBU a : [a] DPOTUSVDUT
B WBMVF GSPN UXP BSHVNFOUT CZ BEEJOH UIF Ԑ UP UIF GSPOU PG
UIF MJTU [a] 5IF MJTU EBUBUZQF JT B TVN UZQF UIPVHI CFDBVTF
JU JT FJUIFS BO FNQUZ MJTU PS B TJOHMF WBMVF XJUI NPSF MJTU ƈ OPU
CPUI
*O &OHMJTI POF DBO SFBE UIJT BT

data [] a = [] | a : [a]
-- [1] [2] [3] [4] [5] [6]

 5IF EBUBUZQF XJUI UIF UZQF DPOTUSVDUPS []

 UBLFT B TJOHMF UZQF DPOTUSVDUPS BSHVNFOU ƉBƊ

 BU UIF UFSN MFWFM DBO CF DPOTUSVDUFE WJB

 OVMMBSZ DPOTUSVDUPS []
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 PS JU DBO CF DPOTUSVDUFE CZ

 EBUB DPOTUSVDUPS (:) XIJDI JT B QSPEVDU PG B WBMVF PG UIF


UZQF a XF NFOUJPOFE JO UIF UZQF DPOTUSVDUPS BOE B WBMVF
PG UZQF [a] UIBU JT ƌNPSF MJTUƍ

5IF DPOT DPOTUSVDUPS (:) JT BO JOƶY EBUB DPOTUSVDUPS BOE


HPFT CFUXFFO UIF UXP BSHVNFOUT a BOE [a] UIBU JU BDDFQUT 4JODF
JU UBLFT UXP BSHVNFOUT JU JT B QSPEVDU PG UIPTF UXP BSHVNFOUT
MJLF UIF UVQMF UZQF (a, b) 6OMJLF B UVQMF IPXFWFS UIJT DPO
TUSVDUPS JT SFDVSTJWF CFDBVTF JU NFOUJPOT JUT PXO UZQF [a] BT
POF PG UIF NFNCFST PG UIF QSPEVDU
*G ZPVƊSF BO FYQFSJFODFE QSPHSBNNFS PS UPPL B $4 DMBTT BU
TPNF QPJOU ZPV NBZ CF GBNJMJBS XJUI TJOHMZMJOLFE MJTUT 5IJT
JT B GBJS EFTDSJQUJPO PG UIF MJTU EBUBUZQF JO )BTLFMM BMUIPVHI
BWFSBHF DBTF QFSGPSNBODF JO TPNF TJUVBUJPOT DIBOHFT EVF
UP OPOTUSJDU FWBMVBUJPO IPXFWFS JU DBO DPOUBJO JOƶOJUF EBUB
XIJDI NBLFT JU BMTP XPSL BT B TUSFBN EBUBUZQF CVU POF UIBU IBT
UIF PQUJPO PG FOEJOH UIF TUSFBN XJUI UIF [] EBUB DPOTUSVDUPS

 1BUUFSO NBUDIJOH PO MJTUT


8F LOPX XF DBO QBUUFSO NBUDI PO EBUB DPOTUSVDUPST BOE UIF
EBUB DPOTUSVDUPST GPS MJTUT BSF OP FYDFQUJPOT )FSF XF NBUDI
PO UIF ƶSTU BSHVNFOU UP UIF JOƶY (:) DPOTUSVDUPS JHOPSJOH UIF
SFTU PG UIF MJTU BOE SFUVSO UIBU WBMVF
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

Prelude> let myHead (x : _) = x


Prelude> :t myHead
myHead :: [t] -> t
Prelude> myHead [1, 2, 3]
1

8F DBO EP UIF PQQPTJUF BT XFMM

Prelude> let myTail (_ : xs) = xs


Prelude> :t myTail
myTail :: [t] -> [t]
Prelude> myTail [1, 2, 3]
[2,3]

8F EP OFFE UP CF DBSFGVM XJUI GVODUJPOT MJLF UIFTF /FJUIFS


myHead OPS myTail IBT B DBTF UP IBOEMF BO FNQUZ MJTU ƈ JG XF USZ
UP QBTT UIFN BO FNQUZ MJTU BT BO BSHVNFOU UIFZ DBOƊU QBUUFSO
NBUDI

Prelude> myHead []
*** Exception:
Non-exhaustive patterns in function myHead

Prelude> myTail []
*** Exception:
Non-exhaustive patterns in function myTail
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

5IF QSPCMFN JT UIBU UIF UZQF [a] -> a PG myHead JT EFDFQUJWF


CFDBVTF UIF [a] UZQF EPFTOƊU HVBSBOUFF UIBU JUƊMM IBWF BO Ԑ WBMVF
*UƊT OPU HVBSBOUFFE UIBU UIF MJTU XJMM IBWF BU MFBTU POF WBMVF TP
myTail DBO GBJM BT XFMM 0OF QPTTJCJMJUZ JT QVUUJOH JO B CBTF DBTF

myTail :: [a] -> [a]


myTail [] = []
myTail (_ : xs) = xs

*O UIBU DBTF PVS GVODUJPO OPX FWBMVBUFT MJLF UIJT

Prelude> myTail [1..5]


[2,3,4,5]
Prelude> myTail []
[]

6TJOH .BZCF " CFUUFS XBZ UP IBOEMF UIJT TJUVBUJPO JT XJUI B


EBUBUZQF DBMMFE Maybe 8FƊMM TBWF B GVMM USFBUNFOU PG Maybe GPS
B MBUFS DIBQUFS CVU UIJT TIPVME HJWF ZPV TPNF JEFB PG IPX JU
XPSLT 5IF JEFB IFSF JT UIBU JU NBLFT ZPVS GBJMVSF DBTF FYQMJDJU
BOE BT QSPHSBNT HFU MPOHFS BOE NPSF DPNQMFY UIBU DBO CF
RVJUF VTFGVM
-FUƊT USZ BO FYBNQMF VTJOH Maybe XJUI myTail *OTUFBE PG
IBWJOH B CBTF DBTF UIBU SFUVSOT BO FNQUZ MJTU UIF GVODUJPO
XSJUUFO XJUI Maybe XPVME SFUVSO B SFTVMU PG Nothing "T XF DBO
TFF CFMPX UIF Maybe EBUBUZQF IBT UXP QPUFOUJBM WBMVFT Nothing
PS Just a
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

Prelude> :info Maybe


data Maybe a = Nothing | Just a

3FXSJUJOH myTail UP VTF Maybe JT GBJSMZ TUSBJHIUGPSXBSE

safeTail :: [a] -> Maybe [a]


safeTail [] = Nothing
safeTail (x:[]) = Nothing
safeTail (_:xs) = Just xs

/PUJDF UIBU PVS GVODUJPO JT TUJMM QBUUFSO NBUDIJOH PO UIF MJTU


8FƊWF NBEF UIF TFDPOE CBTF DBTF safeTail (x:[]) = Nothing UP
SFƷFDU UIF GBDU UIBU JG ZPVS MJTU IBT POMZ POF WBMVF JOTJEF JU JUT
UBJM JT BO FNQUZ MJTU *G ZPV MFBWF UIJT DBTF PVU UIFO UIJT GVODUJPO
XJMM SFUVSO Just [] GPS MJTUT UIBU IBWF POMZ B IFBE WBMVF 5BLF
B GFX NJOVUFT UP QMBZ BSPVOE XJUI UIJT BOE TFF IPX JU XPSLT
5IFO TFF JG ZPV DBO SFXSJUF UIF myHead GVODUJPO BCPWF VTJOH
Maybe
-BUFS JO UIF CPPL XFƊMM BMTP DPWFS B EBUBUZQF DBMMFE NonEmpty
XIJDI BMXBZT IBT BU MFBTU POF WBMVF BOE BWPJET UIF FNQUZ MJTU
QSPCMFN

 -JTUƊT TZOUBDUJD TVHBS


)BTLFMM IBT TPNF TZOUBDUJD TVHBS UP BDDPNNPEBUF UIF VTF PG
MJTUT TP UIBU ZPV DBO XSJUF
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

Prelude> [1, 2, 3] ++ [4]


[1, 2, 3, 4]

3BUIFS UIBO

Prelude> (1 : 2 : 3 : []) ++ 4 : []
[1,2,3,4]

5IF TZOUBDUJD TVHBS JT IFSF UP BMMPX CVJMEJOH MJTUT JO UFSNT


PG UIF TVDDFTTJWF BQQMJDBUJPOT PG ƉDPOTƊ (:) UP B WBMVF XJUIPVU
IBWJOH UP UFEJPVTMZ UZQF JU BMM PVU
8IFO XF UBML BCPVU MJTUT XF PǒFO UBML BCPVU UIFN JO UFSNT
PG ƌDPOT DFMMTƍ BOE TQJOFT 5IF TZOUBDUJD TVHBS PCTDVSFT UIJT
VOEFSMZJOH DPOTUSVDUJPO CVU MPPLJOH BU UIF EFTVHBSFE WFS
TJPO BCPWF NBZ NBLF JU NPSF DMFBS 5IF DPOT DFMMT BSF UIF
MJTU EBUBUZQFƊT TFDPOE EBUB DPOTUSVDUPS a : [a] UIF SFTVMU PG
SFDVSTJWFMZ QSFQFOEJOH B WBMVF UP ƌNPSF MJTUƍ 5IF DPOT DFMM JT
B DPODFQUVBM TQBDF UIBU WBMVFT NBZ JOIBCJU
5IF TQJOF JT UIF DPOOFDUJWF TUSVDUVSF UIBU IPMET UIF DPOT
DFMMT UPHFUIFS BOE JO QMBDF "T XF XJMM TPPO TFF UIJT TUSVDUVSF
OFTUT UIF DPOT DFMMT SBUIFS UIBO PSEFSJOH UIFN JO B SJHIUUP
MFǒ SPX #FDBVTF EJƵFSFOU GVODUJPOT NBZ USFBU UIF TQJOF BOE
UIF DPOT DFMMT EJƵFSFOUMZ JU JT JNQPSUBOU UP VOEFSTUBOE UIJT
VOEFSMZJOH TUSVDUVSF
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 6TJOH SBOHFT UP DPOTUSVDU MJTUT


5IFSF BSF TFWFSBM XBZT XF DBO DPOTUSVDU MJTUT 0OF PG UIF
TJNQMFTU JT XJUI SBOHFT 5IF CBTJD TZOUBY JT UP NBLF B MJTU UIBU
IBT UIF FMFNFOU ZPV XBOU UP TUBSU UIF MJTU GSPN GPMMPXFE CZ
UXP EPUT GPMMPXFE CZ UIF WBMVF ZPV XBOU BT UIF ƶOBM FMFNFOU
JO UIF MJTU )FSF BSF TPNF FYBNQMFT VTJOH UIF SBOHF TZOUBY
GPMMPXFE CZ UIF EFTVHBSFE FRVJWBMFOUT VTJOH GVODUJPOT GSPN
UIF Enum UZQFDMBTT

Prelude> [1..10]
[1,2,3,4,5,6,7,8,9,10]
Prelude> enumFromTo 1 10
[1,2,3,4,5,6,7,8,9,10]

Prelude> [1,2..10]
[1,2,3,4,5,6,7,8,9,10]
Prelude> enumFromThenTo 1 2 10
[1,2,3,4,5,6,7,8,9,10]

Prelude> [1,3..10]
[1,3,5,7,9]
Prelude> enumFromThenTo 1 3 10
[1,3,5,7,9]

Prelude> [2,4..10]
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

[2,4,6,8,10]
Prelude> enumFromThenTo 2 4 10
[2,4,6,8,10]

Prelude> ['t'..'z']
"tuvwxyz"
Prelude> enumFromTo 't' 'z'
"tuvwxyz"

5IF UZQFT PG UIF GVODUJPOT VOEFSMZJOH UIF SBOHF TZOUBY BSF

enumFrom :: Enum a => a -> [a]


enumFromThen :: Enum a => a -> a -> [a]

enumFromTo :: Enum a => a -> a -> [a]


enumFromThenTo :: Enum a => a -> a -> a -> [a]

"MM PG UIFTF GVODUJPOT SFRVJSF UIBU UIF UZQF CFJOH ƌSBOHFEƍ


IBWF BO JOTUBODF PG UIF Enum UZQFDMBTT 5IF ƶSTU UXP GVODUJPOT
enumFrom BOE enumFromThen HFOFSBUF MJTUT PG JOEFƶOJUF QPTTJCMZ
JOƶOJUF MFOHUI 'PS JU UP DSFBUF BO JOƶOJUFMZ MPOH MJTU ZPV
NVTU CF SBOHJOH PWFS B UZQF UIBU IBT OP VQQFS CPVOE JO JUT
FOVNFSBUJPO Integer JT TVDI B UZQF :PV DBO NBLF Integer
WBMVFT BT MBSHF BT ZPV IBWF NFNPSZ UP EFTDSJCF
#F BXBSF UIBU enumFromTo NVTU IBWF JUT ƶSTU BSHVNFOU CF
MPXFS UIBO UIF TFDPOE BSHVNFOU
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

Prelude> enumFromTo 3 1
[]
Prelude> enumFromTo 1 3
[1,2,3]

0UIFSXJTF ZPVƊMM KVTU HFU BO FNQUZ MJTU

&YFSDJTF &OVN'SPN5P
4PNF UIJOHT ZPVƊMM XBOU UP LOPX BCPVU UIF Enum UZQFDMBTT

Prelude> :info Enum


class Enum a where
succ :: a -> a
pred :: a -> a
toEnum :: Int -> a
fromEnum :: a -> Int
enumFrom :: a -> [a]
enumFromThen :: a -> a -> [a]
enumFromTo :: a -> a -> [a]
enumFromThenTo :: a -> a -> a -> [a]
Prelude> succ 0
1
Prelude> succ 1
2
Prelude> succ 'a'
'b'
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

8SJUF ZPVS PXO enumFromTo EFƶOJUJPOT GPS UIF UZQFT QSP


WJEFE %P OPU VTF SBOHF TZOUBY UP EP TP *U TIPVME SFUVSO UIF
TBNF SFTVMUT BT JG ZPV EJE [start..stop]

eftBool :: Bool -> Bool -> [Bool]


eftBool = undefined

eftOrd :: Ordering -> Ordering -> [Ordering]


eftOrd = undefined

eftInt :: Int -> Int -> [Int]


eftInt = undefined

eftChar :: Char -> Char -> [Char]


eftChar = undefined

 &YUSBDUJOH QPSUJPOT PG MJTUT


*O UIJT TFDUJPO XFƊMM UBLF B MPPL BU TPNF VTFGVM GVODUJPOT GPS
FYUSBDUJOH QPSUJPOT PG B MJTU BOE EJWJEJOH MJTUT JOUP QBSUT 5IF
ƶSTU UISFF GVODUJPOT IBWF TJNJMBS UZQF TJHOBUVSFT UBLJOH Int
BSHVNFOUT BOE BQQMZJOH UIFN UP B MJTU BSHVNFOU

take :: Int -> [a] -> [a]


drop :: Int -> [a] -> [a]
splitAt :: Int -> [a] -> ([a], [a])
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

8F IBWF TFFO FYBNQMFT PG TPNF PG UIF BCPWF GVODUJPOT JO


QSFWJPVT DIBQUFST CVU UIFZ BSF DPNNPO BOE VTFGVM FOPVHI
UIFZ EFTFSWF SFWJFX
5IF take GVODUJPO UBLFT UIF TQFDJƶFE OVNCFS PG FMFNFOUT
PVU PG B MJTU BOE SFUVSOT B MJTU DPOUBJOJOH KVTU UIPTF FMFNFOUT
"T ZPV DBO TFF JU UBLFT POF BSHVNFOU UIBU JT BO Int BOE BQQMJFT
UIBU UP B MJTU BSHVNFOU )FSFƊT IPX JU XPSLT

Prelude> take 7 ['a'..'z']


"abcdefg"

Prelude> take 3 [1..10]


[1,2,3]

Prelude> take 3 []
[]

/PUJDF UIBU XIFO XF QBTT JU BO FNQUZ MJTU BT BO BSHVNFOU JU


KVTU SFUVSOT BO FNQUZ MJTU 5IFTF MJTUT VTF UIF TZOUBDUJD TVHBS
GPS CVJMEJOH MJTUT XJUI SBOHFT 8F DBO BMTP VTF take XJUI B MJTU
CVJMEJOH GVODUJPO TVDI BT enumFrom 3FNJOEFS enumFrom DBO
HFOFSBUF BO JOƶOJUF MJTU JG UIF UZQF PG MJTU JOIBCJUBOUT JT TVDI
BT Integer BO JOƶOJUF TFU #VU BT MPOH BT XFƊSF POMZ UBLJOH B
DFSUBJO OVNCFS PG FMFNFOUT GSPN UIBU JU XPOƊU HFOFSBUF BO
JOƶOJUF MJTU

Prelude> take 10 (enumFrom 10)


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

[10,11,12,13,14,15,16,17,18,19]

5IF drop GVODUJPO JT TJNJMBS UP take CVU ESPQT UIF TQFDJƶFE


OVNCFS PG FMFNFOUT PƵ UIF CFHJOOJOH PG UIF MJTU "HBJO XF
DBO VTF JU XJUI SBOHFT PS MJTUCVJMEJOH GVODUJPOT

Prelude> drop 5 [1..10]


[6,7,8,9,10]

Prelude> drop 8 ['a'..'z']


"ijklmnopqrstuvwxyz"

Prelude> drop 4 []
[]

Prelude> drop 2 (enumFromTo 10 20)


[12,13,14,15,16,17,18,19,20]

5IF splitAt GVODUJPO DVUT B MJTU JOUP UXP QBSUT BU UIF FMFNFOU
TQFDJƶFE CZ UIF Int BOE NBLFT B UVQMF PG UXP MJTUT

Prelude> splitAt 5 [1..10]


([1,2,3,4,5],[6,7,8,9,10])

Prelude> splitAt 10 ['a'..'z']


("abcdefghij","klmnopqrstuvwxyz")
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

Prelude> splitAt 5 []
([],[])

Prelude> splitAt 3 (enumFromTo 5 15)


([5,6,7],[8,9,10,11,12,13,14,15])

5IF IJHIFSPSEFS GVODUJPOT takeWhile BOE dropWhile BSF B CJU


EJƵFSFOU BT ZPV DBO TFF GSPN UIF UZQF TJHOBUVSFT

takeWhile :: (a -> Bool) -> [a] -> [a]


dropWhile :: (a -> Bool) -> [a] -> [a]

4P UIFTF UBLF BOE ESPQ JUFNT PVU PG B MJTU UIBU NFFU TPNF
DPOEJUJPO BT XF DBO TFF GSPN UIF QSFTFODF PG Bool takeWhile
XJMM UBLF FMFNFOUT PVU PG B MJTU UIBU NFFU UIBU DPOEJUJPO BOE
UIFO TUPQ XIFO JU NFFUT UIF ƶSTU FMFNFOU UIBU EPFTOƊU TBUJTGZ
UIF DPOEJUJPO

Prelude> takeWhile (<3) [1..10]


[1,2]
-- Takes the elements that are less than 3

Prelude> takeWhile (<8) (enumFromTo 5 15)


[5,6,7]
-- Takes the elements that are less than 8

Prelude> takeWhile (>6) [1..10]


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

[]
-- It returns an empty list because it stops
-- taking as soon as the condition isn't met,
-- which in this case is the first element

Prelude> takeWhile (=='a') "abracadabra"


"a"

*O UIF ƶOBM FYBNQMF BCPWF XIZ EPFT JU POMZ SFUVSO B TJOHMF


Ԑ
'JOBMMZ XFƊMM MPPL BU dropWhile XIPTF CFIBWJPS JT QSPCBCMZ
QSFEJDUBCMF CBTFE PO UIF GVODUJPOT BOE UZQF TJHOBUVSFT XFƊWF
BMSFBEZ TFFO JO UIJT TFDUJPO 8F XJMM VTF UIF TBNF BSHVNFOUT
BT XF VTFE XJUI takeWhile TP UIF EJƵFSFODF CFUXFFO UIFN JT
FBTZ UP TFF

Prelude> dropWhile (<3) [1..10]


[3,4,5,6,7,8,9,10]

Prelude> dropWhile (<8) (enumFromTo 5 15)


[8,9,10,11,12,13,14,15]

Prelude> dropWhile (>6) [1..10]


[1,2,3,4,5,6,7,8,9,10]

Prelude> dropWhile (=='a') "abracadabra"


"bracadabra"
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

&YFSDJTFT 5IZ 'FBSGVM 4ZNNFUSZ


 6TJOH takeWhile BOE dropWhile XSJUF B GVODUJPO UIBU UBLFT B
TUSJOH BOE SFUVSOT B MJTU PG TUSJOHT VTJOH TQBDFT UP TFQBSBUF
UIF FMFNFOUT PG UIF TUSJOH JOUP XPSET BT JO UIF GPMMPXJOH
TBNQMF

*Main> myWords "all i wanna do is have some fun"


["all","i","wanna","do","is","have","some","fun"]

 /FYU XSJUF B GVODUJPO UIBU UBLFT B TUSJOH BOE SFUVSOT B MJTU


PG TUSJOHT VTJOH OFXMJOF TFQBSBUPST UP CSFBL VQ UIF TUSJOH
BT JO UIF GPMMPXJOH ZPVS KPC JT UP ƶMM JO UIF VOEFƶOFE
GVODUJPO


module PoemLines where

firstSen = "Tyger Tyger, burning bright\n"


secondSen = "In the forests of the night\n"
thirdSen = "What immortal hand or eye\n"
fourthSen = "Could frame thy fearful symmetry?"
sentences = firstSen ++ secondSen
++ thirdSen ++ fourthSen
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

-- putStrLn sentences -- should print


-- Tyger Tyger, burning bright
-- In the forests of the night
-- What immortal hand or eye
-- Could frame thy fearful symmetry?

-- Implement this
myLines :: String -> [String]
myLines = undefined

-- What we want 'myLines sentences' to equal


shouldEqual =
[ "Tyger Tyger, burning bright"
, "In the forests of the night"
, "What immortal hand or eye"
, "Could frame thy fearful symmetry?"
]

-- The main function here is a small test


-- to ensure you've written your function
-- correctly.
main :: IO ()
main =
print $ "Are they equal? "
++ show (myLines sentences == shouldEqual)
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 /PX MFUƊT MPPL BU XIBU UIPTF UXP GVODUJPOT IBWF JO DPN


NPO 5SZ XSJUJOH B OFX GVODUJPO UIBU QBSBNFUFSJ[FT UIF
DIBSBDUFS ZPVƊSF CSFBLJOH UIF TUSJOH BSHVNFOU PO BOE
SFXSJUF myWords BOE myLines VTJOH JU

 -JTU DPNQSFIFOTJPOT


-JTU DPNQSFIFOTJPOT BSF B NFBOT PG HFOFSBUJOH B OFX MJTU
GSPN B MJTU PS MJTUT 5IFZ DPNF EJSFDUMZ GSPN UIF DPODFQU PG
TFU DPNQSFIFOTJPOT JO NBUIFNBUJDT JODMVEJOH TJNJMBS TZOUBY
5IFZ NVTU IBWF BU MFBTU POF MJTU DBMMFE UIF HFOFSBUPS UIBU HJWFT
UIF JOQVU GPS UIF DPNQSFIFOTJPO UIBU JT QSPWJEFT UIF TFU PG
JUFNT GSPN XIJDI UIF OFX MJTU XJMM CF DPOTUSVDUFE 5IFZ NBZ
IBWF DPOEJUJPOT UP EFUFSNJOF XIJDI FMFNFOUT BSF ESBXO GSPN
UIF MJTU BOEPS GVODUJPOT BQQMJFE UP UIPTF FMFNFOUT
-FUƊT TUBSU CZ MPPLJOH BU B WFSZ TJNQMF FYBNQMF

[ x^2 | x <- [1..10]]


-- [1] [2] [ 3 ]

 5IJT JT UIF PVUQVU GVODUJPO UIBU XJMM BQQMZ UP UIF NFNCFST


PG UIF MJTU XF JOEJDBUF

 5IF QJQF IFSF EFTJHOBUFT UIF TFQBSBUJPO CFUXFFO UIF PVU


QVU GVODUJPO BOE UIF JOQVU

 5IJT JT UIF JOQVU TFU B HFOFSBUPS MJTU BOE B WBSJBCMF UIBU


SFQSFTFOUT UIF FMFNFOUT UIBU XJMM CF ESBXO GSPN UIBU MJTU
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

5IJT TBZT ƌGSPN B MJTU PG OVNCFST GSPN  UBLF (<-)


FBDI FMFNFOU BT BO JOQVU UP UIF PVUQVU GVODUJPOƍ

*O QMBJO &OHMJTI UIBU MJTU DPNQSFIFOTJPO XJMM QSPEVDF B


OFX MJTU UIBU JODMVEFT UIF TRVBSF PG FWFSZ OVNCFS GSPN  UP 

Prelude> [x^2 | x <- [1..10]]


[1,4,9,16,25,36,49,64,81,100]

/PX XFƊMM MPPL BU TPNF XBZT UP WBSZ XIBU FMFNFOUT BSF


ESBXO GSPN UIF HFOFSBUPS MJTU T


"EEJOH QSFEJDBUFT
-JTU DPNQSFIFOTJPOT DBO PQUJPOBMMZ UBLF QSFEJDBUFT UIBU MJNJU
UIF FMFNFOUT ESBXO GSPN UIF HFOFSBUPS MJTU 5IF QSFEJDBUFT
NVTU FWBMVBUF UP #PPM WBMVFT BT JO PUIFS DPOEJUJPOQMBDJOH
GVODUJPO UZQFT XFƊWF MPPLFE BU GPS FYBNQMF HVBSET
 5IFO UIF
JUFNT ESBXO GSPN UIF MJTU BOE QBTTFE UP UIF PVUQVU GVODUJPO
XJMM POMZ CF UIPTF UIBU NFU UIF 5SVF DBTF JO UIF QSFEJDBUF
'PS FYBNQMF MFUƊT TBZ XF XBOUFE B TJNJMBS MJTU DPNQSFIFO
TJPO BT XF VTFE BCPWF CVU UIJT UJNF XF XBOUFE PVS OFX MJTU UP
DPOUBJO UIF TRVBSFT PG POMZ UIF FWFO OVNCFST XIJMF JHOPSJOH
UIF PEET *O UIBU DBTF XF QVU B DPNNB BǒFS PVS HFOFSBUPS MJTU
BOE BEE UIF DPOEJUJPO

Prelude> [x^2 | x <- [1..10], rem x 2 == 0]


[4,16,36,64,100]
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

)FSF XFƊWF TQFDJƶFE UIBU UIF POMZ FMFNFOUT UP UBLF GSPN


UIF HFOFSBUPS MJTU BT ԧ BSF UIPTF UIBU XIFO EJWJEFE CZ  IBWF
B SFNBJOEFS PG [FSP ƈ UIBU JT FWFO OVNCFST
8F DBO BMTP XSJUF MJTU DPNQSFIFOTJPOT UIBU IBWF NVMUJQMF
HFOFSBUPST 0OF UIJOH UP OPUF JT UIBU UIF SJHIUNPTU HFOFSBUPS
XJMM CF FYIBVTUFE ƶSTU UIFO UIF TFDPOE SJHIUNPTU BOE TP PO
'PS FYBNQMF MFUƊT TBZ ZPV XBOUFE UP NBLF B MJTU PG ԧ UP
UIF Ԩ QPXFS JOTUFBE PG TRVBSJOH BMM PG UIFN BT XF EJE BCPWF
4FQBSBUF UIF UXP JOQVUT XJUI B DPNNB BT CFMPX

Prelude> [x^y | x <- [1..5], y <- [2, 3]]


[1,1,4,8,9,27,16,64,25,125]

8IFO XF FYBNJOF UIF SFTVMUJOH MJTU XF TFF UIBU JU JT FBDI


ԧ WBMVF ƶSTU UP UIF TFDPOE QPXFS BOE UIFO UP UIF UIJSE QPXFS
GPMMPXFE CZ UIF OFYU ԧ WBMVF UP UIF TFDPOE BOE UIFO UP UIF
UIJSE BOE TP PO FOEJOH XJUI UIF SFTVMU PG ? BOE ? 8F BSF
BQQMZJOH UIF GVODUJPO UP FBDI QPTTJCMF QBJSJOH PG WBMVFT GSPN
UIF UXP MJTUT XFƊSF CJOEJOH WBMVFT PVU PG *U CFHJOT CZ USZJOH
UP HFU B WBMVF PVU PG UIF MFǒNPTU HFOFSBUPS GSPN XIJDI XFƊSF
HFUUJOH ԧ
8F DPVME QVU B DPOEJUJPO PO UIBU UPP -FUƊT TBZ XF POMZ
XBOU UP SFUVSO UIF MJTU PG WBMVFT UIBU BSF MFTT UIBO  8F BEE
BOPUIFS DPNNB BOE XSJUF PVS QSFEJDBUF

Prelude> [x^y | x <- [1..10], y <- [2, 3], x^y < 200]
[1,1,4,8,9,27,16,64,25,125,36,49,64,81,100]
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

8F DBO VTF NVMUJQMF HFOFSBUPST UP UVSO UXP MJTUT JOUP B MJTU


PG UVQMFT DPOUBJOJOH UIPTF FMFNFOUT BT XFMM 5IF HFOFSBUPS
MJTUT EPOƊU FWFO IBWF UP CF PG UIF TBNF MFOHUI PS EVF UP UIF
OBUVSF PG UIF UVQMF UZQF FWFO UIF TBNF UZQF

Prelude> [(x, y) | x <- [1, 2, 3], y <- [6, 7]]


[(1,6),(1,7),(2,6),(2,7),(3,6),(3,7)]

Prelude> [(x, y) | x <- [1, 2, 3], y <- ['a', 'b']]


[(1,'a'),(1,'b'),(2,'a'),(2,'b'),(3,'a'),(3,'b')]

"HBJO UIF QBUUFSO JT UIBU JU HFOFSBUFT FWFSZ QPTTJCMF UVQMF


GPS UIF ƶSTU ԧ WBMVF UIFO JU NPWFT UP UIF OFYU ԧ WBMVF BOE TP
PO
3FDBMM UIBU UIF ƶSTU MJTU DPNQSFIFOTJPO XF MPPLFE BU HFO
FSBUFE B MJTU PG BMM UIF WBMVFT PG ԧ? XIFO ԧ JT B OVNCFS GSPN
 -FUƊT TBZ ZPV XBOUFE UP VTF UIBU MJTU JO BOPUIFS MJTU DPN
QSFIFOTJPO 'JSTU ZPVƊE XBOU UP HJWF UIBU MJTU B OBNF -FUƊT DBMM
JU ƌNZ4RSƍ

Prelude> let mySqr = [x^2 | x <- [1..5]]

/PX XF DBO VTF UIBU MJTU BT UIF HFOFSBUPS GPS BOPUIFS MJTU
DPNQSFIFOTJPO )FSF XF XJMM MJNJU PVS JOQVU WBMVFT UP UIPTF
UIBU BSF MFTT UIBO  GPS UIF TBLF PG CSFWJUZ

Prelude> let mySqr = [x^2 | x <- [1..5]]


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

Prelude> [(x, y) | x <- mySqr, y <- [1..3], x < 4]


[(1,1),(1,2),(1,3)]

&YFSDJTFT $PNQSFIFOE 5IZ -JTUT


5BLF B MPPL BU UIF GPMMPXJOH GVODUJPOT ƶHVSF XIBU ZPV UIJOL
UIF PVUQVU MJTUT XJMM CF BOE UIFO SVO UIFN JO ZPVS 3&1- UP
WFSJGZ OPUF UIBU ZPV XJMM OFFE UIF mySqr MJTU GSPN BCPWF JO
TDPQF UP EP UIJT


[x | x <- mySqr, rem x 2 == 0]

[(x, y) | x <- mySqr, y <- mySqr, x < 50, y > 50]

take 5 [ (x, y) | x <- mySqr


, y <- mySqr, x < 50, y > 50 ]

-JTU DPNQSFIFOTJPOT XJUI 4USJOHT


*UƊT XPSUI SFNFNCFSJOH UIBU TUSJOHT BSF MJTUT TP MJTU DPNQSFIFO
TJPOT DBO BMTP CF VTFE XJUI TUSJOHT 8FƊSF HPJOH UP JOUSPEVDF
B TUBOEBSE GVODUJPO DBMMFE elem UIBU UFMMT ZPV XIFUIFS BO FM
FNFOU JT JO B MJTU PS OPU *U FWBMVBUFT UP B Bool WBMVF TP JU JT
VTFGVM BT B QSFEJDBUF JO MJTU DPNQSFIFOTJPOT

Prelude> :t elem

3FNJOEFS QSFUFOE Foldable JO UIF UZQF PG elem NFBOT JUƊT B MJTU VOUJM XF DPWFS Foldable
MBUFS
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

elem :: Eq a => a -> [a] -> Bool


Prelude> elem 'a' "abracadabra"
True
Prelude> elem 'a' "Julie"
False

*O UIF ƶSTU DBTF ƉBƊ JT BO FMFNFOU PG ƌBCSBDBEBCSBƍ TP UIBU


FWBMVBUFT UP True CVU JO UIF TFDPOE DBTF UIFSF JT OP ƉBƊ JO
ƌ+VMJFƍ TP XF HFU B False SFTVMU "T ZPV DBO TFF GSPN UIF UZQF
TJHOBUVSF elem EPFTOƊU POMZ XPSL XJUI DIBSBDUFST BOE TUSJOHT
CVU UIBUƊT XIBU XFƊMM VTF JU GPS IFSF -FUƊT TFF JG XF DBO XSJUF B
MJTU DPNQSFIFOTJPO UP SFNPWF BMM UIF MPXFSDBTF MFUUFST GSPN
B TUSJOH )FSF PVS DPOEJUJPO JT UIBU XF POMZ XBOU UP UBLF ԧ
GSPN PVS HFOFSBUPS MJTU XIFO JU NFFUT UIF DPOEJUJPO UIBU JU JT
BO FMFNFOU PG UIF MJTU PG DBQJUBM MFUUFST

Prelude> [x | x <- "Three Letter Acronym", elem x ['A'..'Z']]


"TLA"

-FUƊT TFF JG XF DBO OPX HFOFSBMJ[F UIJT JOUP BO BDSPOZN


HFOFSBUPS UIBU XJMM BDDFQU EJƵFSFOU TUSJOHT BT JOQVUT JOTUFBE PG
GPSDJOH VT UP SFXSJUF UIF XIPMF MJTU DPNQSFIFOTJPO GPS FWFSZ
TUSJOH XF NJHIU XBOU UP GFFE JU 8F XJMM EP UIJT CZ OBNJOH
B GVODUJPO UIBU XJMM UBLF POF BSHVNFOU BOE VTF UIBU BT UIF
HFOFSBUPS TUSJOH GPS PVS MJTU DPNQSFIFOTJPO 4P UIF GVODUJPO
BSHVNFOU BOE UIF HFOFSBUPS TUSJOH XJMM OFFE UP CF UIF TBNF
UIJOH
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

Prelude> let acro xs = [x | x <- xs, elem x ['A'..'Z']]

8F VTF ԧԢ GPS PVS GVODUJPO BSHVNFOU UP JOEJDBUF UP PVSTFMWFT


UIBU JUƊT B MJTU UIBU UIF ԧ JT QMVSBM *U EPFTOƊU IBWF UP CF ZPV
DPVME VTF B EJƵFSFOU WBSJBCMF UIFSF BOE PCUBJO UIF TBNF SFTVMU
*U JT JEJPNBUJD UP VTF B ƌQMVSBMƍ WBSJBCMF GPS MJTU BSHVNFOUT CVU
JU JT OPU OFDFTTBSZ
"MM SJHIU TP XF IBWF PVS acro GVODUJPO XJUI XIJDI XF DBO
HFOFSBUF BDSPOZNT GSPN BOZ TUSJOH

Prelude> acro "Self Contained Underwater Breathing Apparatus"


"SCUBA"
Prelude> acro "National Aeronautics and Space Administration"
"NASA"

(JWFO UIF BCPWF XIBU EP ZPV UIJOL UIJT GVODUJPO XPVME EP

Prelude> let myString xs = [x | x <- xs, elem x "aeiou"]

&YFSDJTFT 4RVBSF $VCF


(JWFO UIF GPMMPXJOH

Prelude> let mySqr = [x^2 | x <- [1..5]]


Prelude> let myCube = [y^3 | y <- [1..5]]

 'JSTU XSJUF BO FYQSFTTJPO UIBU XJMM NBLF UVQMFT PG UIF PVU


QVUT PG mySqr BOE myCube
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 /PX BMUFS UIBU FYQSFTTJPO TP UIBU JU POMZ VTFT UIF Y BOE Z


WBMVFT UIBU BSF MFTT UIBO 

 "QQMZ BOPUIFS GVODUJPO UP UIBU MJTU DPNQSFIFOTJPO UP


EFUFSNJOF IPX NBOZ UVQMFT JOIBCJU ZPVS PVUQVU MJTU

 4QJOFT BOE OPOTUSJDU FWBMVBUJPO


"T XF IBWF TFFO MJTUT BSF B SFDVSTJWF TFSJFT PG DPOT DFMMT a : [a]
UFSNJOBUFE CZ UIF FNQUZ MJTU [] CVU XF XBOU B XBZ UP WJTV
BMJ[F UIJT TUSVDUVSF JO PSEFS UP VOEFSTUBOE UIF XBZT MJTUT HFU
QSPDFTTFE 8IFO XF UBML BCPVU EBUB TUSVDUVSFT JO )BTLFMM QBS
UJDVMBSMZ MJTUT TFRVFODFT BOE USFFT XF UBML BCPVU UIFN IBWJOH
B TQJOF 5IJT JT UIF DPOOFDUJWF TUSVDUVSF UIBU UJFT UIF DPMMFDUJPO
PG WBMVFT UPHFUIFS *O UIF DBTF PG B MJTU UIF TQJOF JT VTVBMMZ UFY
UVBMMZ SFQSFTFOUFE CZ UIF SFDVSTJWF DPOT (:) PQFSBUPST (JWFO
UIF EBUB [1, 2, 3] XF HFU B MJTU UIBU MPPLT MJLF

1 : 2 : 3 : []
or
1 : (2 : (3 : []))

:
/ \
1 :
/ \
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

2 :
/ \
3 []

5IF QSPCMFN XJUI UIF 1 : (2 : (3 : [])) SFQSFTFOUBUJPO XF


VTFE FBSMJFS JT UIBU JU NBLFT JU TFFN MJLF UIF WBMVF 1 FYJTUT
ƌCFGPSFƍ UIF DPOT (:) DFMM UIBU DPOUBJOT JU CVU BDUVBMMZ UIF DPOT
DFMMT DPOUBJO UIF WBMVFT #FDBVTF PG UIJT BOE UIF XBZ OPOTUSJDU
FWBMVBUJPO XPSLT ZPV DBO FWBMVBUF DPOT DFMMT JOEFQFOEFOUMZ
PG XIBU UIFZ DPOUBJO *U JT QPTTJCMF UP FWBMVBUF KVTU UIF TQJOF PG
UIF MJTU XJUIPVU FWBMVBUJOH JOEJWJEVBM WBMVFT *U JT BMTP QPTTJCMF
UP FWBMVBUF POMZ QBSU PG UIF TQJOF PG B MJTU BOE OPU UIF SFTU PG JU
&WBMVBUJPO PG UIF MJTU JO UIJT SFQSFTFOUBUJPO QSPDFFET EPXO
UIF TQJOF $POTUSVDUJOH UIF MJTU XIFO UIBU JT OFDFTTBSZ IPX
FWFS QSPDFFET VQ UIF TQJOF *O UIF FYBNQMF BCPWF UIFO XF
TUBSU XJUI BO JOƶY PQFSBUPS FWBMVBUF UIF BSHVNFOUT  BOE B
OFX DPOT DFMM BOE QSPDFFE EPXOXBSE UP UIF  BOE FNQUZ MJTU
#VU XIFO XF OFFE UP CVJME UIF MJTU UP QSJOU JU JO UIF 3&1- GPS
FYBNQMF JU QSPDFFET GSPN UIF CPUUPN PG UIF MJTU VQ UIF TQJOF
ƶSTU QVUUJOH UIF  JOUP UIF FNQUZ MJTU UIFO BEEJOH UIF  UP
UIF GSPOU PG UIBU MJTU UIFO ƶOBMMZ QVUUJOH UIF  JO UIF GSPOU PG
UIBU #FDBVTF )BTLFMMƊT FWBMVBUJPO JT OPOTUSJDU UIF MJTU JTOƊU DPO
TUSVDUFE VOUJM JUƊT DPOTVNFE ƈ JOEFFE OPUIJOH JT FWBMVBUFE
VOUJM JU NVTU CF 6OUJM JUƊT DPOTVNFE PS ZPV GPSDF TUSJDUOFTT
JO TPNF XBZ UIFSF BSF B TFSJFT PG QMBDFIPMEFST BT B CMVFQSJOU
PG UIF MJTU UIBU DBO CF DPOTUSVDUFE XIFO JUƊT OFFEFE 8FƊMM UBML
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

NPSF BCPVU OPOTUSJDUOFTT TPPO


8FƊSF HPJOH UP CSJOH વ PS CPUUPN CBDL JO UIF GPSN PG undefined
JO PSEFS UP EFNPOTUSBUF TPNF PG UIF FƵFDUT PG OPOTUSJDU FWBMV
BUJPO )FSF XFƊSF HPJOH UP VTF _ UP TZOUBDUJDBMMZ TJHOJGZ WBMVFT
XF BSF JHOPSJOH BOE OPU FWBMVBUJOH 5IF VOEFSTDPSFT SFQSF
TFOU UIF WBMVFT DPOUBJOFE CZ UIF DPOT DFMMT 5IF TQJOF JT UIF
SFDVSTJWF TFSJFT PG DPOT DPOTUSVDUPST TJHOJƶFE CZ (:) BT ZPV
DBO TFF CFMPX

: <------|
/ \ |
_ : <----| This is the "spine"
/ \ |
_ : <--|
/ \
_ []

:PVƊMM TFF UIF UFSN ƉTQJOFƊ VTFE JO SFGFSFODF UP EBUB TUSVD


UVSFT TVDI BT USFFT UIBU BSFOƊU MJTUT *O UIF DBTF PG MJTU UIF TQJOF
JT B MJOFBS TVDDFTTJPO PG POF DPOT DFMM XSBQQJOH BOPUIFS DPOT
DFMM 8JUI EBUB TUSVDUVSFT MJLF USFFT XIJDI XF XJMM DPWFS MBUFS
ZPVƊMM TFF UIBU UIF TQJOF DBO CF OPEFT UIBU DPOUBJO  PS NPSF
OPEFT
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

6TJOH ()$JƊT TQSJOU DPNNBOE


8F DBO VTF B TQFDJBM DPNNBOE JO ()$J DBMMFE sprint UP QSJOU
WBSJBCMFT BOE TFF XIBU IBT CFFO FWBMVBUFE BMSFBEZ XJUI UIF VO
EFSTDPSF SFQSFTFOUJOH FYQSFTTJPOT UIBU IBWFOƊU CFFO FWBMVBUFE
ZFU
" XBSOJOH 8F BMXBZT FODPVSBHF ZPV UP FYQFSJNFOU BOE
FYQMPSF GPS ZPVSTFMG BǒFS TFFJOH UIF FYBNQMFT JO UIJT CPPL CVU
:sprint IBT TPNF CFIBWJPSBM RVJSLT UIBU DBO CF B CJU GSVTUSBUJOH
()$ )BTLFMM IBT TPNF PQQPSUVOJTUJD PQUJNJ[BUJPOT XIJDI
JOUSPEVDF TUSJDUOFTT UP NBLF DPEF GBTUFS XIFO JU XPOƊU DIBOHF
IPX ZPVS DPEF FWBMVBUFT "EEJUJPOBMMZ QPMZNPSQIJTN NFBOT
WBMVFT MJLF Num a => a BSF SFBMMZ XBJUJOH GPS B TPSU PG BSHVNFOU
XIJDI XJMM NBLF JU DPODSFUF UIJT XJMM CF DPWFSFE JO NPSF EFUBJM
JO B MBUFS DIBQUFS
 5P BWPJE UIJT ZPV IBWF UP BTTJHO B NPSF
DPODSFUF UZQF TVDI BT Int PS Double PUIFSXJTF JU TUBZT VOFWBM
VBUFE _ JO :sprintƊT PVUQVU *G ZPV DBO LFFQ UIFTF DBWFBUT UP
:sprintƊT CFIBWJPS JO NJOE JU DBO CF VTFGVM 0UIFSXJTF JG ZPV
ƶOE JU DPOGVTJOH EPOƊU TXFBU JU BOE XBJU GPS VT UP FMBCPSBUF
NPSF EFFQMZ JO UIF DIBQUFS PO OPOTUSJDUOFTT
-FUƊT EFƶOF B MJTU VTJOH enumFromTo XIJDI JT UBOUBNPVOU UP
VTJOH TZOUBY MJLF ['a'..'z'] UIFO BTL GPS UIF TUBUF PG blah XJUI
SFTQFDU UP XIFUIFS JU IBT CFFO FWBMVBUFE

Prelude> let blah = enumFromTo 'a' 'z'


Prelude> :sprint blah
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

blah = _

5IF blah = _ JOEJDBUFT UIBU blah JT UPUBMMZ VOFWBMVBUFE


/FYU XFƊMM UBLF POF WBMVF GSPN blah BOE UIFO FWBMVBUF JU CZ
GPSDJOH ()$J UP QSJOU UIF FYQSFTTJPO

Prelude> take 1 blah


"a"
Prelude> :sprint blah
blah = 'a' : _

4P XFƊWF FWBMVBUFE B DPOT DFMM : BOE UIF ƶSTU WBMVF 'a'


5IFO XF UBLF UXP WBMVFT BOE QSJOU UIFN ƈ XIJDI GPSDFT
FWBMVBUJPO PG UIF TFDPOE DPOT DFMM BOE UIF TFDPOE WBMVF

Prelude> take 2 blah


"ab"
Prelude> :sprint blah
blah = 'a' : 'b' : _

"TTVNJOH UIJT JT B DPOUJHVPVT ()$J TFTTJPO UIF ƶSTU DPOT


DFMM BOE WBMVF XFSF BMSFBEZ GPSDFE
8F DBO LFFQ HPJOH XJUI UIJT FWBMVBUJOH UIF MJTU POF WBMVF
BU B UJNF

Prelude> take 3 blah


"abc"
Prelude> :sprint blah
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

blah = 'a' : 'b' : 'c' : _

5IF length GVODUJPO JT POMZ TUSJDU JO UIF TQJOF NFBOJOH JU


POMZ GPSDFT FWBMVBUJPO PG UIF TQJOF PG B MJTU OPU UIF WBMVFT
TPNFUIJOH XF DBO TFF JG XF USZ UP ƶOE UIF MFOHUI PG B MJTU PG
VOEFƶOFE WBMVFT #VU XIFO XF VTF length PO blah :sprint XJMM
CFIBWF BT UIPVHI XF IBE GPSDFE FWBMVBUJPO PG UIF WBMVFT BT
XFMM

Prelude> length blah


26
Prelude> :sprint blah
blah = "abcdefghijklmnopqrstuvwxyz"

5IBU UIF JOEJWJEVBM DIBSBDUFST XFSF TIPXO BT FWBMVBUFE


BOE OPU FYDMVTJWFMZ UIF TQJOF BǒFS HFUUJOH UIF MFOHUI PG blah JT
POF PG UIF VOGPSUVOBUF BGPSFNFOUJPOFE RVJSLT PG IPX ()$J
FWBMVBUFT DPEF

4QJOFT BSF FWBMVBUFE JOEFQFOEFOUMZ PG WBMVFT


7BMVFT JO )BTLFMM HFU SFEVDFE UP XFBL IFBE OPSNBM GPSN CZ
EFGBVMU #Z ƉOPSNBM GPSNƊ XF NFBO UIBU UIF FYQSFTTJPO JT GVMMZ
FWBMVBUFE Ɖ8FBL IFBE OPSNBM GPSNƊ NFBOT UIF FYQSFTTJPO JT
POMZ FWBMVBUFE BT GBS BT JT OFDFTTBSZ UP SFBDI B EBUB DPOTUSVDUPS
8FBL IFBE OPSNBM GPSN 8)/'
JT B MBSHFS TFU BOE DPO
UBJOT CPUI UIF QPTTJCJMJUZ UIBU UIF FYQSFTTJPO JT GVMMZ FWBMV
BUFE OPSNBM GPSN
BOE UIF QPTTJCJMJUZ UIBU UIF FYQSFTTJPO IBT
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

CFFO FWBMVBUFE UP UIF QPJOU PG BSSJWJOH BU B EBUB DPOTUSVDUPS PS


MBNCEB BXBJUJOH BO BSHVNFOU 'PS BO FYQSFTTJPO JO XFBL IFBE
OPSNBM GPSN GVSUIFS FWBMVBUJPO NBZ CF QPTTJCMF PODF BOPUIFS
BSHVNFOU JT QSPWJEFE *G OP GVSUIFS JOQVUT BSF QPTTJCMF UIFO
JU JT TUJMM JO 8)/' CVU BMTP JO OPSNBM GPSN /'
 8FƊSF HPJOH
UP FYQMBJO UIJT NPSF GVMMZ MBUFS JO UIF CPPL JO UIF DIBQUFS PO
OPOTUSJDUOFTT XIFO XF TIPX ZPV IPX DBMMCZOFFE XPSLT BOE
UIF JNQMJDBUJPOT GPS )BTLFMM 'PS OPX XFƊMM KVTU MPPL BU B GFX
FYBNQMFT UP HFU B TFOTF GPS XIBU NJHIU CF HPJOH PO
#FMPX XF MJTU TPNF FYQSFTTJPOT BOE XIFUIFS UIFZ BSF JO
8)/' /' CPUI PS OFJUIFS

(1, 2) -- WHNF & NF

5IJT ƶSTU FYBNQMF JT JO OPSNBM GPSN BOE JT GVMMZ FWBMVBUFE


"OZUIJOH JO OPSNBM GPSN JT CZ EFƶOJUJPO BMTP JO XFBL IFBE
OPSNBM GPSN CFDBVTF XFBL IFBE JT BO FYQSFTTJPO XIJDI JT
FWBMVBUFE VQ UP BU MFBTU UIF ƶSTU EBUB DPOTUSVDUPS /PSNBM GPSN
FYDFFET UIBU CZ SFRVJSJOH UIBU BMM TVCFYQSFTTJPOT CF GVMMZ
FWBMVBUFE )FSF UIF DPNQPOFOUT PG UIF WBMVF BSF UIF UVQMF
EBUB DPOTUSVDUPS BOE UIF WBMVFT  BOE 

(1, 1 + 1)

5IJT FYBNQMF JT JO 8)/' CVU OPU /' 5IF (+) BQQMJFE UP


JUT BSHVNFOUT DPVME CF FWBMVBUFE CVU IBTOƊU CFFO ZFU

\x -> x * 10 -- WHNF & NF


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

5IJT BOPOZNPVT GVODUJPO JT JO OPSNBM GPSN CFDBVTF XIJMF


(*) IBT CFFO BQQMJFE UP UXP BSHVNFOUT PG B TPSU JU DBOOPU CF
SFEVDFE GVSUIFS VOUJM UIF PVUFS x -> ... IBT CFFO BQQMJFE
8JUI OPUIJOH GVSUIFS UP SFEVDF JU JT JO OPSNBM GPSN

"Papu" ++ "chon"

5IJT TUSJOH DPODBUFOBUJPO JT JO OFJUIFS 8)/' OPS /' UIJT


JT CFDBVTF UIF ƌPVUFSNPTUƍ DPNQPOFOU PG UIF FYQSFTTJPO JT B
GVODUJPO (++) XIPTF BSHVNFOUT BSF GVMMZ BQQMJFE CVU JU IBTOƊU
CFFO FWBMVBUFE 8IFSFBT UIF GPMMPXJOH XPVME CF JO 8)/'
CVU OPU /'

(1, "Papu" ++ "chon")

8IFO XF EFƶOF B MJTU BOE EFƶOF BMM JUT WBMVFT JU JT JO /'


BOE BMM JUT WBMVFT BSF LOPXO 5IFSFƊT OPUIJOH MFǒ UP FWBMVBUF
BU UIBU QPJOU TVDI BT JO UIF GPMMPXJOH FYBNQMF

Prelude> let num :: [Int]; num = [1, 2, 3]


Prelude> :sprint num
num = [1,2,3]

8F DBO BMTP DPOTUSVDU B MJTU UISPVHI SBOHFT PS GVODUJPOT


*O UIJT DBTF UIF MJTU JT JO 8)/' CVU OPU /' 5IF DPNQJMFS
POMZ FWBMVBUFT UIF IFBE PS ƶSTU OPEF PG UIF HSBQI CVU KVTU UIF
DPOT DPOTUSVDUPS OPU UIF WBMVF PS SFTU PG UIF MJTU JU DPOUBJOT
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

8F LOPX UIFSFƊT B WBMVF PG UZQF Ԑ JO UIF DPOT DFMM XF IBWFOƊU


FWBMVBUFE BOE B ƌSFTU PG MJTUƍ XIJDI NJHIU FJUIFS CF UIF FNQUZ
MJTU [] XIJDI FOET UIF MJTU PS BOPUIFS DPOT DFMM ƈ XF EPOƊU LOPX
XIJDI CFDBVTF XF IBWFOƊU FWBMVBUFE UIF OFYU [a] WBMVF ZFU 8F
TBX UIBU BCPWF JO UIF :sprint TFDUJPO BOE ZPV DBO TFF UIBU
FWBMVBUJPO PG UIF ƶSTU WBMVFT EPFT OPU GPSDF FWBMVBUJPO PG UIF
SFTU PG UIF MJTU

Prelude> let myNum :: [Int]; myNum = [1..10]


Prelude> :sprint myNum
myNum = _
Prelude> take 2 myNum
[1,2]
Prelude> :sprint myNum
myNum = 1 : 2 : _

5IJT JT BO FYBNQMF PG 8)/' FWBMVBUJPO *UƊT XFBL IFBE


OPSNBM GPSN CFDBVTF UIF MJTU IBT UP CF DPOTUSVDUFE CZ UIF
SBOHF BOE JUƊT POMZ HPJOH UP FWBMVBUF BT GBS BT JU IBT UP 8JUI
take 2 XF POMZ OFFE UP FWBMVBUF UIF ƶSTU UXP DPOT DFMMT BOE
UIF WBMVFT UIFZ DPOUBJO XIJDI JT XIZ XIFO XF VTFE :sprint
XF POMZ TBX 1 : 2 : _ &WBMVBUJOH UP OPSNBM GPSN XPVMEƊWF
NFBOU SFDVSTJOH UISPVHI UIF FOUJSF MJTU GPSDJOH OPU POMZ UIF
FOUJSF TQJOF CVU BMTP UIF WBMVFT FBDI DPOT DFMM DPOUBJOFE
*O UIFTF USFF SFQSFTFOUBUJPOT FWBMVBUJPO PS DPOTVNQUJPO PG
UIF MJTU HPFT EPXO UIF TQJOF 5IF GPMMPXJOH JT B SFQSFTFOUBUJPO
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

PG B MJTU UIBU JTOƊU TQJOF TUSJDU BOE JT BXBJUJOH TPNFUIJOH UP GPSDF


UIF FWBMVBUJPO

:
/ \
_ _

#Z EFGBVMU JU TUPQT IFSF BOE OFWFS FWBMVBUFT FWFO UIF ƶSTU


DPOT DFMM VOMFTT JUƊT GPSDFE UP BT XF TBX
)PXFWFS GVODUJPOT UIBU BSF TQJOF TUSJDU DBO GPSDF DPNQMFUF
FWBMVBUJPO PG UIF TQJOF PG UIF MJTU FWFO JG UIFZ EPOƊU GPSDF FWBM
VBUJPO PG FBDI WBMVF 1BUUFSO NBUDIJOH JT TUSJDU CZ EFGBVMU TP
QBUUFSO NBUDIJOH PO DPOT DFMMT DBO NFBO GPSDJOH TQJOF TUSJDU
OFTT JG ZPVS GVODUJPO EPFTOƊU TUPQ SFDVSTJOH UIF MJTU *U DBO
FWBMVBUF UIF TQJOF POMZ PS UIF TQJOF BT XFMM BT UIF WBMVFT UIBU
JOIBCJU FBDI DPOT DFMM EFQFOEJOH PO DPOUFYU
0O UIF PUIFS IBOE length JT TUSJDU JO UIF TQJOF CVU OPU UIF
WBMVFT *G XF EFƶOFE B MJTU TVDI BT [1, 2, 3] VTJOH length PO JU
XPVME GPSDF FWBMVBUJPO PG UIF FOUJSF TQJOF XJUIPVU BDDPNQB
OZJOH TUSJDUOFTT JO UIF WBMVFT

:
/ \
_ :
/ \
_ :
/ \
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

_ []

8F DBO TFF UIJT JG XF VTF length CVU NBLF POF PG UIF WBMVFT
CPUUPN XJUI UIF undefined WBMVF BOE TFF XIBU IBQQFOT

Prelude> let x = [1, undefined, 3]


Prelude> length x
3

5IF ƶSTU BOE UIJSE WBMVFT JO UIF MJTU XFSF OVNCFST CVU UIF
TFDPOE WBMVF XBT undefined BOE length EJEOƊU NBLF JU DSBTI
8IZ #FDBVTF length NFBTVSFT UIF MFOHUI PG B MJTU XIJDI POMZ
SFRVJSFT SFDVSTJOH UIF TQJOF BOE DPVOUJOH IPX NBOZ DPOT DFMMT
UIFSF BSF 8F DPVME EFƶOF PVS PXO length GVODUJPO PVSTFMWFT
MJLF TP

-- *Not* identical to the length function in Prelude


length :: [a] -> Integer
length [] = 0
length (_:xs) = 1 + length xs

0OF UIJOH UP OPUF JT UIBU XF VTF _ UP JHOPSF UIF WBMVFT JO PVS


BSHVNFOUT PS UIBU BSF QBSU PG B QBUUFSO NBUDI *O UIJT DBTF XF
QBUUFSONBUDIFE PO UIF (:) EBUB DPOTUSVDUPS CVU XBOUFE UP
JHOPSF UIF WBMVF XIJDI JT UIF ƶSTU BSHVNFOU )PXFWFS JUƊT OPU
B NFSF DPOWFOUJPO UP CJOE SFGFSFODFT XF EPOƊU DBSF BCPVU PO
UIF MFǒ IBOE TJEF UP _ :PV DBOƊU CJOE BSHVNFOUT UP UIF OBNF
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

ƍ@ƍ JUƊT QBSU PG UIF MBOHVBHF 5IJT JT QBSUMZ TP UIF DPNQJMFS


LOPXT GPS B DFSUBJOUZ ZPV XPOƊU FWFS FWBMVBUF TPNFUIJOH JO
UIBU QBSUJDVMBS DBTF $VSSFOUMZ JG ZPV USZ VTJOH _ PO UIF SJHIU
IBOE TJEF JO UIF EFƶOJUJPO JUƊMM UIJOL ZPVƊSF USZJOH UP SFGFS UP
B IPMF
8FƊSF POMZ GPSDJOH UIF (:) DPOTUSVDUPST BOE UIF [] BU UIF
FOE JO PSEFS UP DPVOU UIF OVNCFS PG WBMVFT DPOUBJOFE CZ UIF
MJTU

: <-|
/ \ |
|-> _ : <-|
| / \ | These got evaluated (forced)
|-> _ : <-|
| / \ |
|-> _ [] <-|
|
| These did not

)PXFWFS length XJMM UISPX BO FSSPS PO B CPUUPN WBMVF JG


QBSU PG UIF TQJOF JUTFMG JT CPUUPN

Prelude> let x = [1] ++ undefined ++ [3]


Prelude> x
[1*** Exception: Prelude.undefined
Prelude> length x
*** Exception: Prelude.undefined
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

1SJOUJOH UIF MJTU GBJMT BMUIPVHI JU HFUT BT GBS BT QSJOUJOH UIF


ƶSTU [ BOE UIF ƶSTU WBMVF BOE BUUFNQUJOH UP HFU UIF MFOHUI BMTP
GBJMT CFDBVTF JU DBOƊU DPVOU VOEFƶOFE TQJOF WBMVFT
*UƊT QPTTJCMF UP XSJUF GVODUJPOT XIJDI XJMM GPSDF CPUI UIF
TQJOF BOE UIF WBMVFT sum JT BO FYBNQMF CFDBVTF JO PSEFS UP
SFUVSO B SFTVMU BU BMM JU NVTU SFUVSO UIF TVN PG BMM WBMVFT JO UIF
MJTU
8FƊMM XSJUF PVS PXO TVN GVODUJPO GPS UIF TBLF PG EFNPO
TUSBUJPO

mySum :: Num a => [a] -> a


mySum [] = 0
mySum (x : xs) = x + mySum xs

'JSTU UIF + PQFSBUPS JT TUSJDU JO CPUI PG JUT BSHVNFOUT TP UIBU


XJMM GPSDF FWBMVBUJPO PG UIF WBMVFT BOE UIF mySum xs 5IFSFGPSF
mySum XJMM LFFQ SFDVSTJOH VOUJM JU IJUT UIF FNQUZ MJTU BOE NVTU
TUPQ 5IFO JU XJMM TUBSU HPJOH CBDL VQ UIF TQJOF PG UIF MJTU
TVNNJOH UIF JOIBCJUBOUT BT JU HPFT *U MPPLT TPNFUIJOH MJLF
UIJT UIF [FSP SFQSFTFOUT PVS FNQUZ MJTU


Prelude> mySum [1..5]


1 + (2 + (3 + (4 + (5 + 0))))
1 + (2 + (3 + (4 + 5)))
1 + (2 + (3 + 9))
1 + (2 + 12)
1 + 14
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

15

8F XJMM CF SFUVSOJOH UP UIJT UPQJD BU WBSJPVT QPJOUT JO UIF


CPPL CFDBVTF EFWFMPQJOH JOUVJUJPO GPS )BTLFMMƊT FWBMVBUJPO
TUSBUFHJFT UBLFT UJNF BOE QSBDUJDF *G ZPV EPOƊU GFFM MJLF ZPV
GVMMZ VOEFSTUBOE JU BU UIJT QPJOU UIBUƊT 0, *UƊT B DPNQMFY UPQJD
BOE JUƊT CFUUFS UP BQQSPBDI JU JO TUBHFT

&YFSDJTFT #PUUPN .BEOFTT


8JMM JU CMPX VQ

 8JMM UIF GPMMPXJOH FYQSFTTJPO SFUVSO B WBMVF PS CF વ

[x^y | x <- [1..5], y <- [2, undefined]]

 take 1 $ [x^y | x <- [1..5], y <- [2, undefined]]

 sum [1, undefined, 3]

 length [1, 2, undefined]

 length $ [1, 2, 3] ++ undefined

 take 1 $ filter even [1, 2, 3, undefined]

 take 1 $ filter even [1, 3, undefined]

 take 1 $ filter odd [1, 3, undefined]


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 take 2 $ filter odd [1, 3, undefined]

 take 3 $ filter odd [1, 3, undefined]

*OUFSNJTTJPO *T JU JO OPSNBM GPSN

'PS FBDI FYQSFTTJPO CFMPX EFUFSNJOF XIFUIFS JUƊT JO

 OPSNBM GPSN XIJDI JNQMJFT XFBL IFBE OPSNBM GPSN

 XFBL IFBE OPSNBM GPSN POMZ PS

 OFJUIFS

3FNFNCFS UIBU BO FYQSFTTJPO DBOOPU CF JO OPSNBM GPSN PS


XFBL IFBE OPSNBM GPSN JG UIF PVUFSNPTU QBSU PG UIF FYQSFTTJPO
JTOƊU B EBUB DPOTUSVDUPS *U DBOƊU CF JO OPSNBM GPSN JG BOZ QBSU
PG UIF FYQSFTTJPO JT VOFWBMVBUFE

 [1, 2, 3, 4, 5]

 1 : 2 : 3 : 4 : _

 enumFromTo 1 10

 length [1, 2, 3, 4, 5]

 sum (enumFromTo 1 10)

 ['a'..'m'] ++ ['n'..'z']

 (_, 'b')
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 5SBOTGPSNJOH MJTUT PG WBMVFT


8F IBWF BMSFBEZ TFFO IPX XF DBO NBLF SFDVSTJWF GVODUJPOT
XJUI TFMGSFGFSFOUJBM FYQSFTTJPOT *UƊT B VTFGVM UPPM BOE B DPSF
QBSU PG UIF MPHJD PG )BTLFMM *O USVUI JO QBSU CFDBVTF )BTLFMM
VTFT OPOTUSJDU FWBMVBUJPO XF UFOE UP VTF IJHIFSPSEFS GVOD
UJPOT GPS USBOTGPSNJOH EBUB SBUIFS UIBO NBOVBMMZ SFDVSTJOH
PWFS BOE PWFS
'PS FYBNQMF POF DPNNPO UIJOH ZPV XPVME XBOU UP EP JT
SFUVSO B MJTU XJUI B GVODUJPO BQQMJFE VOJGPSNMZ UP BMM WBMVFT
XJUIJO UIF MJTU 5P EP TP ZPV OFFE B GVODUJPO UIBU JT JOIFSFOUMZ
SFDVSTJWF BOE DBO BQQMZ UIBU GVODUJPO UP FBDI NFNCFS PG UIF
MJTU 'PS UIJT QVSQPTF XF DBO VTF FJUIFS UIF map PS fmap GVODUJPOT
map DBO POMZ CF VTFE XJUI [] fmap JT EFƶOFE JO B UZQFDMBTT
OBNFE Functor BOE DBO CF BQQMJFE UP EBUB PUIFS UIBO MJTUT 8F
XJMM MFBSO NPSF BCPVU Functor MBUFS GPS OPX XFƊMM GPDVT KVTU PO
UIF MJTU VTBHF )FSF BSF TPNF FYBNQMFT VTJOH map BOE fmap

Prelude> map (+1) [1, 2, 3, 4]


[2,3,4,5]
Prelude> map (1-) [1, 2, 3, 4]
[0,-1,-2,-3]
Prelude> fmap (+1) [1, 2, 3, 4]
[2,3,4,5]
Prelude> fmap (2*) [1, 2, 3, 4]
[2,4,6,8]
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

Prelude> fmap id [1, 2, 3]


[1,2,3]
Prelude> map id [1, 2, 3]
[1,2,3]

5IF UZQFT PG map BOE fmap SFTQFDUJWFMZ BSF

map :: (a -> b) -> [a] -> [b]


fmap :: Functor f => (a -> b) -> f a -> f b

-FUƊT MPPL BU IPX UIF UZQFT MJOF VQ XJUI B QSPHSBN TUBSUJOH


XJUI map

map :: (a -> b) -> [a] -> [b]

map (+1)
-- (a -> b) becomes more specific,
-- is resolved to: Num a => a -> a

Prelude> :t map (+1)


map (+1) :: Num b => [b] -> [b]
-- now we see it will take one list of Num
-- as an argument and return a list of Num
-- as a result

5IF UZQF PG fmap XJMM CFIBWF TJNJMBSMZ


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

fmap :: Functor f => (a -> b) -> f a -> f b


-- notice this has the Functor typeclass constraint

fmap (+1)
-- again, (a -> b) is now more specific

Prelude> :t fmap (+1)


fmap (+1) :: (Num b, Functor f) => f b -> f b
-- a bit different from map because the Functor
-- typeclass includes more than just lists!

)FSFƊT IPX map JT EFƶOFE JO #BTF

map :: (a -> b) -> [a] -> [b]


map _ [] = []
-- [1] [2] [3]
map f (x:xs) = f x : map f xs
-- [4] [5] [6] [7] [8]

 _ JT VTFE IFSF UP JHOPSF UIF GVODUJPO BSHVNFOU CFDBVTF


XF EPOƊU OFFE JU

 8F BSF QBUUFSO NBUDIJOH PO UIF [] FNQUZ MJTU DBTF CFDBVTF


-JTU JT B TVN UZQF XJUI UXP DBTFT BOE XF NVTU IBOEMF CPUI
FWFSZ UJNF XF QBUUFSO NBUDI PS DBTF PO B MJTU WBMVF

 8F SFUVSO UIF [] FNQUZ MJTU WBMVF CFDBVTF XIFO UIFSF BSF


OP WBMVFT JUƊT UIF POMZ DPSSFDU UIJOH XF DBO EP *G ZPV
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

BUUFNQU UP EP BOZUIJOH FMTF UIF UZQFDIFDLFS XJMM TXBU


ZPV

 8F CJOE UIF GVODUJPO BSHVNFOU UP UIF OBNF ԕ BT JU NFSJUT


OP OBNF NPSF TQFDJƶD UIBO UIJT ԕ BOE Ԗ BSF DPNNPO
OBNFT GPS OPOTQFDJƶD GVODUJPO WBMVFT JO )BTLFMM 5IJT JT
UIF GVODUJPO XF BSF NBQQJOH PWFS UIF MJTU WBMVF XJUI map

 8F EP OPU MFBWF UIF FOUJSF MJTU BSHVNFOU CPVOE BT B TJOHMF


OBNF 4JODF XFƊWF BMSFBEZ QBUUFSONBUDIFE UIF [] FNQUZ
MJTU DBTF XF LOPX UIFSF NVTU CF BU MFBTU POF WBMVF JO
UIF MJTU )FSF XF QBUUFSO NBUDI JOUP UIF (:) TFDPOE EBUB
DPOTUSVDUPS PG UIF MJTU XIJDI JT B QSPEVDU ԧ JT UIF TJOHMF
WBMVF PG UIF DPOT QSPEVDU ԧԢ JT UIF SFTU PG UIF MJTU

 8F BQQMZ PVS GVODUJPO ԕ UP UIF TJOHMF WBMVF ԧ 5IJT QBSU


PG UIF map GVODUJPO JT XIBU BDUVBMMZ BQQMJFT UIF GVODUJPO
BSHVNFOU UP UIF DPOUFOUT PG UIF MJTU

 8F (:) DPOT UIF WBMVF SFUVSOFE CZ UIF FYQSFTTJPO f x POUP


UIF IFBE PG UIF SFTVMU PG mapƊJOH UIF SFTU PG UIF MJTU %BUB JT
JNNVUBCMF JO )BTLFMM 8IFO XF NBQ XF EP OPU NVUBUF
UIF FYJTUJOH MJTU CVU CVJME B OFX MJTU XJUI UIF WBMVFT UIBU
SFTVMU GSPN BQQMZJOH UIF GVODUJPO

 8F DBMM map JUTFMG BQQMJFE UP ԕ BOE ԧԢ 5IJT FYQSFTTJPO JT UIF


SFTU PG UIF MJTU XJUI UIF GVODUJPO ԕ BQQMJFE UP FBDI WBMVF
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

)PX EP XF XSJUF PVU XIBU map f EPFT /PUF UIJT PSEFS PG


FWBMVBUJPO EPFTOƊU SFQSFTFOU UIF QSPQFS OPOTUSJDU FWBMVBUJPO
PSEFS CVU EPFT HJWF BO JEFB PG XIBUƊT HPJOH PO
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

map (+1) [1, 2, 3]


-- desugared, (:) is infixr 5, so it's right-associative
map (+1) (1 : (2 : (3 : [])))

-- Not an empty list, so second pattern-match in map fires.


-- Apply (+1) to value, then map
(+1) 1 : map (+1) (2 : (3 : []))

-- Apply (+1) to the next value, cons onto the


-- result of mapping over the rest
(+1) 1 : ((+1) 2 : (map (+1) (3 : [])))

-- Last time we'll trigger the second-case of map


(+1) 1 : ((+1) 2 : ((+1) 3 : (map (+1) [])))

-- Now we trigger the base-case that handles empty list


-- and return the empty list.
(+1) 1 : ((+1) 2 : ((+1) 3 : []))

-- Now we reduce
2 : ((+1) 2 : ((+1) 3 : []))
2 : 3 : (+1) 3 : []
2 : 3 : 4 : [] == [2, 3, 4]

6TJOH UIF TZOUBDUJD TVHBS PG MJTU IFSFƊT BO BQQSPYJNBUJPO PG


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

XIBU map JT EPJOH GPS VT

map f [1, 2, 3] == [f 1, f 2, f 3]

map (+1) [1, 2, 3]


[(+1) 1, (+1) 2, (+1) 3]
[2, 3, 4]

0S VTJOH UIF TQJOF TZOUBY XF JOUSPEVDFE FBSMJFS

:
/ \
1 :
/ \
2 :
/ \
3 []

map (+1) [1, 2, 3]

:
/ \
(+1) 1 :
/ \
(+1) 2 :
/ \
(+1) 3 []
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

"T XF NFOUJPOFE BCPWF UIFTF SFQSFTFOUBUJPOT EP OPU BD


DPVOU GPS OPOTUSJDU FWBMVBUJPO $SVDJBMMZ map EPFTOƊU BDUVBMMZ
USBWFSTF UIF XIPMF MJTU BOE BQQMZ UIF GVODUJPO JNNFEJBUFMZ
5IF GVODUJPO JT BQQMJFE UP UIF WBMVFT ZPV GPSDF PVU PG UIF MJTU
POF CZ POF 8F DBO TFF UIJT CZ TFMFDUJWFMZ MFBWJOH TPNF WBMVFT
VOEFƶOFE

Prelude> map (+1) [1, 2, 3]


[2,3,4]

-- the whole list was forced because


-- GHCi printed the list that resulted

Prelude> (+1) undefined


*** Exception: Prelude.undefined

Prelude> (1, undefined)


(1,*** Exception: Prelude.undefined
Prelude> fst $ (1, undefined)
1

Prelude> map (+1) [1, 2, undefined]


[2,3,*** Exception: Prelude.undefined

Prelude> take 2 $ map (+1) [1, 2, undefined]


[2,3]
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

*O UIF ƶOBM FYBNQMF UIF undefined WBMVF XBT OFWFS GPSDFE


BOE UIFSF XBT OP FSSPS CFDBVTF XF VTFE take 2 UP SFRVFTU POMZ
UIF ƶSTU UXP FMFNFOUT 8JUI map (+1) XF POMZ GPSDF BT NBOZ
WBMVFT BT DPOT DFMMT XF GPSDFE 8FƊMM POMZ GPSDF UIF WBMVFT JG
XF FWBMVBUF UIF SFTVMU WBMVF JO UIF MJTU UIBU UIF NBQ GVODUJPO
SFUVSOT
5IF TJHOJƶDBOU QBSU IFSF JT UIBU TUSJDUOFTT EPFTOƊU QSPDFFE
POMZ PVUTJEFJO 8F DBO IBWF MB[JMZ FWBMVBUFE DPEF FH map

XSBQQFE BSPVOE B TUSJDU DPSF FH +


 *O GBDU XF DBO DIPPTF UP
BQQMZ MB[JOFTT BOE TUSJDUOFTT JO IPX XF FWBMVBUF UIF TQJOF PS
UIF MFBWFT JOEFQFOEFOUMZ " DPNNPO NBOUSB GPS QFSGPSNBODF
TFOTJUJWF DPEF JO )BTLFMM JT ƌMB[Z JO UIF TQJOF TUSJDU JO UIF
MFBWFTƍ 8FƊMM DPWFS UIJT QSPQFSMZ MBUFS XIFO XF UBML BCPVU
OPOTUSJDUOFTT BOE EBUB TUSVDUVSFT BMUIPVHI NBOZ )BTLFMM VTFST
SBSFMZ XPSSZ BCPVU UIJT
:PV DBO VTF map BOE fmap XJUI PUIFS GVODUJPOT BOE MJTU UZQFT
BT XFMM *O UIJT FYBNQMF XF VTF UIF fst GVODUJPO UP SFUVSO B
MJTU PG UIF ƶSTU FMFNFOU PG FBDI UVQMF JO B MJTU PG UVQMFT

Prelude> map fst [(2, 3), (4, 5), (6, 7), (8, 9)]
[2,4,6,8]

Prelude> fmap fst [(2, 3), (4, 5), (6, 7), (8, 9)]
[2,4,6,8]

*O UIJT FYBNQMF XF NBQ B QBSUJBMMZ BQQMJFE take GVODUJPO


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

Prelude> map (take 3) [[1..5], [1..5], [1..5]]


[[1,2,3],[1,2,3],[1,2,3]]

/FYU XFƊMM NBQ BO if-then-else PWFS B MJTU VTJOH BO BOPOZ


NPVT GVODUJPO 5IJT MJTU XJMM ƶOE BOZ WBMVF FRVBM UP  OFHBUF
JU BOE UIFO SFUVSO UIF MJTU

Prelude> map (\x -> if x == 3 then (-x) else (x)) [1..10]


[1,2,-3,4,5,6,7,8,9,10]

"U UIJT QPJOU ZPV DBO USZ ZPVS IBOE BU NBQQJOH EJƵFSFOU
GVODUJPOT VTJOH UIJT BT B NPEFM 8F SFDPNNFOE HFUUJOH DPN
GPSUBCMF XJUI NBQQJOH CFGPSF NPWJOH PO UP UIF 'PMET DIBQUFS

&YFSDJTFT .PSF #PUUPNT


"T BMXBZT XF FODPVSBHF ZPV UP USZ ƶHVSJOH PVU UIF BOTXFST
CFGPSF ZPV FOUFS UIFN JOUP ZPVS 3&1-

 8JMM UIF GPMMPXJOH FYQSFTTJPO SFUVSO B WBMVF PS CF વ

take 1 $ map (+1) [undefined, 2, 3]

 8JMM UIF GPMMPXJOH FYQSFTTJPO SFUVSO B WBMVF

take 1 $ map (+1) [1, undefined, 3]

 8JMM UIF GPMMPXJOH FYQSFTTJPO SFUVSO B WBMVF

take 2 $ map (+1) [1, undefined, 3]


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 8IBU EPFT UIF GPMMPXJOH NZTUFSZ GVODUJPO EP 8IBU JT JUT


UZQF %FTDSJCF JU UP ZPVSTFMG PS B MPWFE POF
JO TUBOEBSE
&OHMJTI BOE UIFO UFTU JU PVU JO UIF 3&1- UP NBLF TVSF ZPV
XFSF DPSSFDU

itIsMystery xs = map (\x -> elem x "aeiou") xs

 8IBU XJMM CF UIF SFTVMU PG UIF GPMMPXJOH GVODUJPOT

B
map (^2) [1..10]

C
map minimum [[1..10], [10..20], [20..30]]
-- n.b. `minimum` is not the same function
-- as the `min` that we used before

D
map sum [[1..5], [1..5], [1..5]]

 #BDL JO UIF 'VODUJPOT DIBQUFS ZPV XSPUF B GVODUJPO DBMMFE


foldBool 5IBU GVODUJPO FYJTUT JO B NPEVMF LOPXO BT %BUB#PPM
BOE JT DBMMFE bool 8SJUF B GVODUJPO UIBU EPFT UIF TBNF PS
TJNJMBS JG ZPV XJTI
BT UIF map (if-then-else) GVODUJPO ZPV
TBX BCPWF CVU VTFT bool JOTUFBE PG UIF if-then-else TZOUBY
:PVS ƶSTU TUFQ TIPVME CF CSJOHJOH UIF bool GVODUJPO JOUP
TDPQF CZ UZQJOH import Data.Bool BU ZPVS 1SFMVEF QSPNQU
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 'JMUFSJOH MJTUT PG WBMVFT


8IFO XF UBMLFE BCPVU GVODUJPO DPNQPTJUJPO JO UIF 'VODUJPOT
DIBQUFS XF VTFE B GVODUJPO DBMMFE filter UIBU UBLFT B MJTU BT
JOQVU BOE SFUVSOT B OFX MJTU DPOTJTUJOH TPMFMZ PG UIF WBMVFT JO
UIF JOQVU MJTU UIBU NFFU B DFSUBJO DPOEJUJPO BT JO UIJT FYBNQMF
XIJDI ƶOET UIF FWFO OVNCFST PG B MJTU BOE SFUVSOT B OFX MJTU
PG KVTU UIPTF WBMVFT

Prelude> filter even [1..10]


[2,4,6,8,10]

-FUƊT OPX UBLF B DMPTFS MPPL BU filter filter IBT UIF GPMMPX
JOH EFƶOJUJPO

filter :: (a -> Bool) -> [a] -> [a]


filter _ [] = []
filter pred (x:xs)
| pred x = x : filter pred xs
| otherwise = filter pred xs

'JMUFSJOH UBLFT B GVODUJPO UIBU SFUVSOT B Bool WBMVF NBQT


UIBU GVODUJPO PWFS B MJTU BOE SFUVSOT B OFX MJTU PG BMM UIF WBMVFT
UIBU NFU UIF DPOEJUJPO *UƊT JNQPSUBOU UP SFNJOE PVSTFMWFT UIBU
UIJT GVODUJPO BT XF DBO TFF JO UIF EFƶOJUJPO CVJMET B OFX MJTU
JODMVEJOH WBMVFT UIBU NFFU UIF DPOEJUJPO BOE FYDMVEJOH UIF
POFT UIBU EP OPU ƈ JU EPFT OPU NVUBUF UIF FYJTUJOH MJTU
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

8F IBWF TFFO IPX filter XPSLT XJUI odd BOE even BMSFBEZ
8F IBWF BMTP TFFO POF FYBNQMF BMPOH UIF MJOFT PG UIJT

Prelude> filter (== 'a') "abracadabra"


"aaaaa"

"T ZPV NJHIU TVTQFDU GSPN XIBU XFƊWF TFFO PG )0'T UIPVHI
filter DBO IBOEMF NBOZ UZQFT PG BSHVNFOUT 5IF GPMMPXJOH FY
BNQMF EPFT UIF TBNF UIJOH BT filter even CVU XJUI BOPOZNPVT
GVODUJPO TZOUBY

Prelude> filter (\x -> (rem x 2) == 0) [1..20]


[2,4,6,8,10,12,14,16,18,20]

8F DPWFSFE MJTU DPNQSFIFOTJPOT FBSMJFS BT B XBZ PG ƶMUFSJOH


MJTUT BT XFMM $PNQBSF UIF GPMMPXJOH

Prelude> filter (\x -> elem x "aeiou") "abracadabra"


"aaaaa"
Prelude> [x | x <- "abracadabra", elem x "aeiou"]
"aaaaa"

"T UIFZ TBZ UIFSFƊT NPSF UIBO POF XBZ UP TLJO B DBU
"HBJO XF SFDPNNFOE BU UIJT QPJOU ZPV USZ XSJUJOH TPNF
ƶMUFS GVODUJPOT PG ZPVS PXO UP HFU DPNGPSUBCMF XJUI UIF QBU
UFSO
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

&YFSDJTFT 'JMUFSJOH
 (JWFO UIF BCPWF IPX NJHIU XF XSJUF B ƶMUFS GVODUJPO UIBU
XPVME HJWF VT BMM UIF NVMUJQMFT PG  PVU PG B MJTU GSPN 

 3FDBMMJOH XIBU XF MFBSOFE BCPVU GVODUJPO DPNQPTJUJPO


IPX DPVME XF DPNQPTF UIF BCPWF GVODUJPO XJUI UIF length
GVODUJPO UP UFMM VT IPX NBOZ NVMUJQMFT PG  UIFSF BSF
CFUXFFO  BOE 

 /FYU XFƊSF HPJOH UP XPSL PO SFNPWJOH BMM BSUJDMFT ƊUIFƊ ƊBƊ


BOE ƊBOƊ
GSPN TFOUFODFT :PV XBOU UP HFU UP TPNFUIJOH
UIBU XPSLT MJLF UIJT

Prelude> myFilter "the brown dog was a goof"


["brown","dog","was","goof"]

:PV NBZ SFDBMM UIBU FBSMJFS JO UIJT DIBQUFS XF BTLFE ZPV


UP XSJUF B GVODUJPO UIBU TFQBSBUFT B TUSJOH JOUP B MJTU PG
TUSJOHT CZ TFQBSBUJOH UIFN BU TQBDFT 5IBU JT B TUBOEBSE
MJCSBSZ GVODUJPO DBMMFE words :PV NBZ DPOTJEFS TUBSUJOH
UIJT FYFSDJTF CZ VTJOH words PS ZPVS WFSTJPO PG DPVSTF


 ;JQQJOH MJTUT


;JQQJOH MJTUT UPHFUIFS JT B NFBOT PG DPNCJOJOH WBMVFT GSPN
NVMUJQMF MJTUT JOUP B TJOHMF MJTU 3FMBUFE GVODUJPOT MJLF zipWith
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

BMMPX ZPV UP VTF B DPNCJOJOH GVODUJPO UP QSPEVDF B MJTU PG


SFTVMUT GSPN UXP MJTUT
'JSTU MFUƊT MPPL BU zip

Prelude> :t zip
zip :: [a] -> [b] -> [(a, b)]

Prelude> zip [1, 2, 3] [4, 5, 6]


[(1,4),(2,5),(3,6)]

0OF UIJOH UP OPUF JT UIBU zip TUPQT BT TPPO BT POF PG UIF MJTUT
SVOT PVU PG WBMVFT

Prelude> zip [1, 2] [4, 5, 6]


[(1,4),(2,5)]
Prelude> zip [1, 2, 3] [4]
[(1,4)]

"OE XJMM SFUVSO BO FNQUZ MJTU JG FJUIFS PG UIF MJTUT JT FNQUZ

Prelude> zip [] [1..1000000000000000000]


[]

zip QSPDFFET VOUJM UIF TIPSUFTU MJTU FOET

Prelude> zip ['a'] [1..1000000000000000000]


[('a',1)]
Prelude> zip [1..100] ['a'..'c']
[(1,'a'),(2,'b'),(3,'c')]
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

8F DBO VTF unzip UP SFDPWFS UIF MJTUT BT UIFZ XFSF CFGPSF


UIFZ XFSF [JQQFE

Prelude> zip [1, 2, 3] [4, 5, 6]


[(1,4),(2,5),(3,6)]
Prelude> unzip $ zip [1, 2, 3] [4, 5, 6]
([1,2,3],[4,5,6])
Prelude> fst $ unzip $ zip [1, 2, 3] [4, 5, 6]
[1,2,3]
Prelude> snd $ unzip $ zip [1, 2, 3] [4, 5, 6]
[4,5,6]

+VTU CF BXBSF UIBU JOGPSNBUJPO DBO CF MPTU JO UIJT QSPDFTT


CFDBVTF zip NVTU TUPQ PO UIF TIPSUFTU MJTU

Prelude> snd $ unzip $ zip [1, 2] [4, 5, 6]


[4,5]

8F DBO BMTP VTF zipWith UP BQQMZ B GVODUJPO UP UIF WBMVFT PG


UXP MJTUT JO QBSBMMFM

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]


-- [1] [2] [3] [4]

 " GVODUJPO XJUI UXP BSHVNFOUT /PUJDF IPX UIF UZQF


WBSJBCMFT PG UIF BSHVNFOUT BOE SFTVMU BMJHO XJUI UIF UZQF
WBSJBCMFT JO UIF MJTUT
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 5IF ƶSTU JOQVU MJTU

 5IF TFDPOE JOQVU MJTU

 5IF PVUQVU MJTU DSFBUFE GSPN BQQMZJOH UIF GVODUJPO UP UIF


WBMVFT JO UIF JOQVU MJTUT

" CSJFG EFNPOTUSBUJPO PG IPX zipWith XPSLT

Prelude> zipWith (+) [1, 2, 3] [10, 11, 12]


[11,13,15]

Prelude> zipWith (*) [1, 2, 3] [10, 11, 12]


[10,22,36]

Prelude> zipWith (==) ['a'..'f'] ['a'..'m']


[True,True,True,True,True,True]

Prelude> zipWith max [10, 5, 34, 9] [6, 8, 12, 7]


[10,8,34,9]

;JQQJOH FYFSDJTFT
 8SJUF ZPVS PXO WFSTJPO PG zip :: [a] -> [b] -> [(a, b)]
BOE FOTVSF JU CFIBWFT UIF TBNF BT UIF PSJHJOBM

 %P XIBU ZPV EJE GPS zip CVU OPX GPS zipWith :: (a -> b
-> c) -> [a] -> [b] -> [c]
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 3FXSJUF ZPVS zip JO UFSNT PG UIF zipWith ZPV XSPUF

 $IBQUFS &YFSDJTFT


5IF ƶSTU TFU PG FYFSDJTFT IFSF XJMM NPTUMZ CF SFWJFX CVU XJMM
BMTP JOUSPEVDF ZPV UP TPNF OFX UIJOHT 5IF TFDPOE TFU JT
NPSF DPODFQUVBMMZ DIBMMFOHJOH CVU EPFT OPU VTF BOZ TZOUBY PS
DPODFQUT XF IBWFOƊU BMSFBEZ TUVEJFE *G ZPV HFU TUVDL JU NBZ
IFMQ UP ƷJQ CBDL UP B SFMFWBOU TFDUJPO BOE SFWJFX

%BUB$IBS
5IFTF ƶSTU GFX FYFSDJTFT BSF TUSBJHIUGPSXBSE CVU XJMM JOUSPEVDF
ZPV UP TPNF OFX MJCSBSZ GVODUJPOT BOE SFWJFX TPNF PG XIBU
XFƊWF MFBSOFE TP GBS 4PNF PG UIF GVODUJPOT XF XJMM VTF IFSF
BSF OPU TUBOEBSE JO 1SFMVEF BOE TP IBWF UP CF JNQPSUFE GSPN
B NPEVMF DBMMFE %BUB$IBS :PV NBZ EP TP JO B TPVSDF ƶMF SFD
PNNFOEFE
PS BU UIF 1SFMVEF QSPNQU XJUI UIF TBNF QISBTF
import Data.Char XSJUF UIBU BU UIF UPQ PG ZPVS TPVSDF ƶMF
 5IJT
CSJOHT JOUP TDPQF B CVODI PG OFX TUBOEBSE GVODUJPOT XF DBO
QMBZ XJUI UIBU PQFSBUF PO $IBS BOE 4USJOH UZQFT

 2VFSZ UIF UZQFT PG isUpper BOE toUpper

 (JWFO UIF GPMMPXJOH CFIBWJPST XIJDI XPVME XF VTF UP


XSJUF B GVODUJPO UIBU ƶMUFST BMM UIF VQQFSDBTF MFUUFST PVU
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

PG B String 8SJUF UIBU GVODUJPO TVDI UIBU HJWFO UIF JOQVU


ƌ)C&G-S-Y0 ƍ ZPVS GVODUJPO XJMM SFUVSO ƌ)&--0ƍ

Prelude Data.Char> isUpper 'J'


True
Prelude Data.Char> toUpper 'j'
'J'

 8SJUF B GVODUJPO UIBU XJMM DBQJUBMJ[F UIF ƶSTU MFUUFS PG B


4USJOH BOE SFUVSO UIF FOUJSF 4USJOH 'PS FYBNQMF JG HJWFO
UIF BSHVNFOU ƌKVMJF ƍ JU XJMM SFUVSO ƌ+VMJFƍ

 /PX NBLF B OFX WFSTJPO PG UIBU GVODUJPO UIBU JT SFDVSTJWF


TVDI UIBU JG ZPV HJWF JU UIF JOQVU ƌXPPUƍ JU XJMM IPMMFS CBDL
BU ZPV ƌ8005ƍ 5IF UZQF TJHOBUVSF XPOƊU DIBOHF CVU
ZPV XJMM XBOU UP BEE B CBTF DBTF

 5P EP UIF ƶOBM FYFSDJTF JO UIJT TFDUJPO XFƊMM OFFE BOPUIFS


TUBOEBSE GVODUJPO GPS MJTUT DBMMFE head 2VFSZ UIF UZQF PG
head BOE FYQFSJNFOU XJUI JU UP TFF XIBU JU EPFT /PX XSJUF
B GVODUJPO UIBU XJMM DBQJUBMJ[F UIF ƶSTU MFUUFS PG B 4USJOH
BOE SFUVSO POMZ UIBU MFUUFS BT UIF SFTVMU

 $PPM (PPE XPSL /PX SFXSJUF JU BT B DPNQPTFE GVODUJPO


5IFO GPS GVO SFXSJUF JU QPJOUGSFF
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

$JQIFST

8FƊMM TUJMM CF VTJOH %BUB$IBS GPS UIJT OFYU FYFSDJTF :PV TIPVME
TBWF UIFTF FYFSDJTFT JO B NPEVMF DBMMFE $JQIFS CFDBVTF XFƊMM
CF DPNJOH CBDL UP UIFN JO MBUFS DIBQUFST :PVƊMM CF XSJUJOH B
$BFTBS DJQIFS GPS OPX CVU XFƊMM TVHHFTU TPNF WBSJBUJPOT PO
UIF CBTJD QSPHSBN JO MBUFS DIBQUFST
" $BFTBS DJQIFS JT B TJNQMF TVCTUJUVUJPO DJQIFS JO XIJDI
FBDI MFUUFS JT SFQMBDFE CZ UIF MFUUFS UIBU JT B ƶYFE OVNCFS PG
QMBDFT EPXO UIF BMQIBCFU GSPN JU :PV XJMM ƶOE WBSJBUJPOT PO
UIJT BMM PWFS UIF QMBDF ƈ ZPV DBO TIJǒ MFǒXBSE PS SJHIUXBSE
GPS BOZ OVNCFS PG TQBDFT " SJHIUXBSE TIJǒ PG  NFBOT UIBU
Ɗ"Ɗ XJMM CFDPNF Ɗ%Ɗ BOE Ɗ#Ɗ XJMM CFDPNF Ɗ& Ɗ GPS FYBNQMF *G ZPV
EJE B MFǒXBSE TIJǒ PG  UIFO ƊBƊ XPVME CFDPNF ƊWƊ BOE TP GPSUI
:PVS HPBM JO UIJT FYFSDJTF JT UP XSJUF B CBTJD $BFTBS DJQIFS
UIBU TIJǒT SJHIUXBSE :PV DBO TUBSU CZ IBWJOH UIF OVNCFS PG
TQBDFT UP TIJǒ ƶYFE CVU JUƊT NPSF DIBMMFOHJOH UP XSJUF B DJQIFS
UIBU BMMPXT ZPV UP WBSZ UIF OVNCFS PG TIJǒT TP UIBU ZPV DBO
FODPEF ZPVS TFDSFU NFTTBHFT EJƵFSFOUMZ FBDI UJNF
5IFSF BSF $BFTBS DJQIFST XSJUUFO JO )BTLFMM BMM PWFS UIF
JOUFSOFU CVU UP NBYJNJ[F UIF MJLFMJIPPE UIBU ZPV DBO XSJUF
ZPVST XJUIPVU QFFLJOH BU UIPTF XFƊMM QSPWJEF B DPVQMF PG UJQT
8IFO ZPVST JT XPSLJOH UIF XBZ ZPV XBOU JU UP XF XPVME
FODPVSBHF ZPV UP UIFO MPPL BSPVOE BOE DPNQBSF ZPVS TPMVUJPO
UP PUIFST PVU UIFSF
5IF ƶSTU MJOFT PG ZPVS UFYU ƶMF TIPVME MPPL MJLF UIJT
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

module Cipher where

import Data.Char

%BUB$IBS JODMVEFT UXP GVODUJPOT DBMMFE ord BOE chr UIBU DBO
CF VTFE UP BTTPDJBUF B $IBS XJUI JUT *OU SFQSFTFOUBUJPO JO UIF
6OJDPEF TZTUFN BOE WJDF WFSTB

*Cipher> :t chr
chr :: Int -> Char
*Cipher> :t ord
ord :: Char -> Int

6TJOH UIFTF GVODUJPOT JT PQUJPOBM UIFSF BSF PUIFS XBZT ZPV


DBO QSPDFFE XJUI TIJǒJOH CVU VTJOH chr BOE ord NJHIU TJNQMJGZ
UIF QSPDFTT B CJU
:PV XBOU ZPVS TIJǒ UP XSBQ CBDL BSPVOE UP UIF CFHJOOJOH PG
UIF BMQIBCFU TP UIBU JG ZPV IBWF B SJHIUXBSE TIJǒ PG  GSPN Ɗ[ Ɗ
ZPV FOE VQ CBDL BU ƊDƊ BOE OPU TPNFXIFSF JO UIF WBTU 6OJDPEF
IJOUFSMBOET %FQFOEJOH PO IPX ZPVƊWF TFU UIJOHT VQ UIJT
NJHIU CF B CJU USJDLZ $POTJEFS TUBSUJOH GSPN B CBTF DIBSBDUFS
FH ƊBƊ
BOE VTJOH mod UP FOTVSF ZPVƊSF POMZ TIJǒJOH PWFS UIF
 TUBOEBSE DIBSBDUFST PG UIF &OHMJTI BMQIBCFU
:PV TIPVME JODMVEF BO unCaesar GVODUJPO UIBU XJMM EFDJQIFS
ZPVS UFYU BT XFMM *O B MBUFS DIBQUFS XF XJMM UFTU JU
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

8SJUJOH ZPVS PXO TUBOEBSE GVODUJPOT


#FMPX BSF UIF PVUMJOFT PG TPNF TUBOEBSE GVODUJPOT 5IF HPBM
IFSF JT UP XSJUF ZPVS PXO WFSTJPOT PG UIFTF UP HBJO B EFFQFS
VOEFSTUBOEJOH PG SFDVSTJPO PWFS MJTUT BOE IPX UP NBLF GVOD
UJPOT ƷFYJCMF FOPVHI UP BDDFQU B WBSJFUZ PG JOQVUT :PV DPVME
ƶHVSF PVU IPX UP MPPL VQ UIF BOTXFST CVU ZPV XPOƊU EP UIBU
CFDBVTF ZPV LOPX ZPVƊE POMZ CF DIFBUJOH ZPVSTFMG PVU PG UIF
LOPXMFEHF 3JHIU
-FUƊT MPPL BU BO FYBNQMF PG XIBU XFƊSF BǒFS IFSF 5IF and
GVODUJPO DBO UBLF B MJTU PG #PPM WBMVFT BOE SFUVSOT 5SVF JG BOE
POMZ JG OP WBMVFT JO UIF MJTU BSF 'BMTF )FSFƊT IPX ZPV NJHIU
XSJUF ZPVS PXO WFSTJPO PG JU

-- direct recursion, not using (&&)


myAnd :: [Bool] -> Bool
myAnd [] = True
myAnd (x:xs) = if x == False then False else myAnd xs

-- direct recursion, using (&&)


myAnd :: [Bool] -> Bool
myAnd [] = True
myAnd (x:xs) = x && myAnd xs

/PUF UIBU JG ZPVƊSF VTJOH ()$  PS OFXFS UIF GVODUJPOT and any BOE all IBWF CFFO
BCTUSBDUFE GSPN CFJOH VTBCMF POMZ XJUI MJTUT UP CFJOH VTBCMF XJUI BOZ EBUBUZQF UIBU IBT BO
JOTUBODF PG UIF UZQFDMBTT 'PMEBCMF *U TUJMM XPSLT XJUI MJTUT KVTU UIF TBNF BT JU EJE CFGPSF
1SPDFFE BTTVSFE UIBU XFƊMM DPWFS UIJT MBUFS
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

"OE OPX UIF GVO CFHJOT

 myOr SFUVSOT 5SVF JG BOZ #PPM JO UIF MJTU JT 5SVF

myOr :: [Bool] -> Bool


myOr = undefined

 myAny SFUVSOT 5SVF JG a -> Bool BQQMJFE UP BOZ PG UIF WBMVFT


JO UIF MJTU SFUVSOT 5SVF

myAny :: (a -> Bool) -> [a] -> Bool


myAny = undefined

&YBNQMF GPS WBMJEBUJOH myAny

Prelude> myAny even [1, 3, 5]


False
Prelude> myAny odd [1, 3, 5]
True

 "ǒFS ZPV XSJUF UIF SFDVSTJWF myElem XSJUF BOPUIFS WFSTJPO


UIBU VTFT any
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

-- the built-in version of 'elem' in GHC 7.10


-- and newer has a type that uses Foldable
-- instead of the list type specifically. You
-- can ignore that and write the concrete
-- version that works only for list.

myElem :: Eq a => a -> [a] -> Bool

Prelude> myElem 1 [1..10]


True
Prelude> myElem 1 [2..10]
False

 *NQMFNFOU myReverse

myReverse :: [a] -> [a]


myReverse = undefined

Prelude> myReverse "blah"


"halb"
Prelude> myReverse [1..5]
[5,4,3,2,1]

 squish ƷBUUFOT B MJTU PG MJTUT JOUP B MJTU

squish :: [[a]] -> [a]


squish = undefined
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 squishMap NBQT B GVODUJPO PWFS B MJTU BOE DPODBUFOBUFT UIF


SFTVMUT

squishMap :: (a -> [b]) -> [a] -> [b]


squishMap = undefined

Prelude> squishMap (\x -> [1, x, 3]) [2]


[1,2,3]
Prelude> squishMap (\x -> "WO "++[x]++" HOO ") "123"
"WO 1 HOO WO 2 HOO WO 3 HOO "

 squishAgain ƷBUUFOT B MJTU PG MJTUT JOUP B MJTU 5IJT UJNF SFVTF


UIF squishMap GVODUJPO

squishAgain :: [[a]] -> [a]


squishAgain = undefined

 myMaximumBy UBLFT B DPNQBSJTPO GVODUJPO BOE B MJTU BOE


SFUVSOT UIF HSFBUFTU FMFNFOU PG UIF MJTU CBTFE PO UIF MBTU
WBMVF UIBU UIF DPNQBSJTPO SFUVSOFE GT GPS *G ZPV JNQPSU
maximumBy GSPN Data.List ZPVƊMM TFF UIF UZQF JT

Foldable t => (a -> a -> Ordering) -> t a -> a

SBUIFS UIBO

(a -> a -> Ordering) -> [a] -> a


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

myMaximumBy :: (a -> a -> Ordering) -> [a] -> a


myMaximumBy = undefined

Prelude> let xs = [1, 53, 9001, 10]


Prelude> myMaximumBy compare xs
9001

 myMinimumBy UBLFT B DPNQBSJTPO GVODUJPO BOE B MJTU BOE


SFUVSOT UIF MFBTU FMFNFOU PG UIF MJTU CBTFE PO UIF MBTU WBMVF
UIBU UIF DPNQBSJTPO SFUVSOFE -5 GPS

myMinimumBy :: (a -> a -> Ordering) -> [a] -> a


myMinimumBy = undefined

Prelude> let xs = [1, 53, 9001, 10]


Prelude> myMinimumBy compare xs
1

6TJOH UIF myMinimumBy BOE myMaximumBy GVODUJPOT XSJUF ZPVS


PXO WFSTJPOT PG maximum BOE minimum *G ZPV IBWF ()$
 PS OFXFS ZPVƊMM TFF B UZQF DPOTUSVDUPS UIBU XBOUT B
'PMEBCMF JOTUBODF JOTUFBE PG B MJTU BT IBT CFFO UIF DBTF GPS
NBOZ GVODUJPOT TP GBS
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

myMaximum :: (Ord a) => [a] -> a


myMaximum = undefined

myMinimum :: (Ord a) => [a] -> a


myMinimum = undefined

 %FƶOJUJPOT
 *O UZQF UIFPSZ B 1SPEVDU UZQF JT B UZQF NBEF PG B TFU PG UZQFT
DPNQPVOEFE PWFS FBDI PUIFS *O )BTLFMM XF SFQSFTFOU
QSPEVDUT VTJOH UVQMFT PS EBUB DPOTUSVDUPST XJUI NPSF UIBO
POF BSHVNFOU 5IF ƌDPNQPVOEJOHƍ JT GSPN FBDI UZQF
BSHVNFOU UP UIF EBUB DPOTUSVDUPS SFQSFTFOUJOH B WBMVF UIBU
DPFYJTUT XJUI BMM UIF PUIFS WBMVFT TJNVMUBOFPVTMZ 1SPEVDUT
PG UZQFT SFQSFTFOU B DPOKVODUJPO ƌBOE ƍ PG UIPTF UZQFT *G
ZPV IBWF B QSPEVDU PG #PPM BOE *OU ZPVS UFSNT XJMM FBDI
DPOUBJO B #PPM BOE *OU WBMVF

 *O UZQF UIFPSZ B 4VN UZQF PG UXP UZQFT JT B UZQF XIPTF


UFSNT BSF UFSNT JO FJUIFS UZQF CVU OPU TJNVMUBOFPVTMZ *O
)BTLFMM TVN UZQFT BSF SFQSFTFOUFE VTJOH UIF QJQF | JO B
EBUBUZQF EFƶOJUJPO 4VNT PG UZQFT SFQSFTFOU B EJTKVODUJPO
ƌPS ƍ PG UIPTF UZQFT *G ZPV IBWF B TVN PG #PPM BOE *OU
ZPVS UFSNT XJMM CF FJUIFS B #PPM WBMVF PS BO *OU WBMVF

 $POT JT PSEJOBSJMZ VTFE BT B WFSC UP TJHOJGZ UIBU B MJTU WBMVF


$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

IBT CFFO DSFBUFE CZ DPOTƊJOH B WBMVF POUP UIF IFBE PG


BOPUIFS MJTU WBMVF *O )BTLFMM (:) JT UIF DPOT PQFSBUPS GPS
UIF MJTU UZQF *U JT B EBUB DPOTUSVDUPS EFƶOFE JO UIF MJTU
EBUBUZQF

1 : [2, 3]
-- [a] [b]

[1, 2, 3]
-- [c]

(:) :: a -> [a] -> [a]


-- [d] [e] [f]

B
5IF OVNCFS  UIF WBMVF XF BSF DPOTJOH
C
" MJTU PG UIF OVNCFS  GPMMPXFE CZ UIF OVNCFS 
D
5IF ƶOBM SFTVMU PG DPOTJOH  POUP [2, 3]
E
5IF UZQF WBSJBCMF Ԑ DPSSFTQPOET UP 1 UIF WBMVF XF
DPOTFE POUP UIF MJTU WBMVF
F
5IF ƶSTU PDDVSSFODF PG UIF UZQF [a] JO UIF DPOT PQFS
BUPSƊT UZQF DPSSFTQPOET UP UIF TFDPOE BOE ƶOBM BSHV
NFOU (:) BDDFQUT XIJDI XBT [2, 3]
G
5IF TFDPOE BOE ƶOBM PDDVSSFODF PG UIF UZQF [a] JO UIF
DPOT PQFSBUPSƊT UZQF DPSSFTQPOET UP UIF ƶOBM SFTVMU
[1, 2, 3]
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

 $POT DFMM JT B EBUB DPOTUSVDUPS BOE B QSPEVDU PG UIF UZQFT


a BOE [a] BT EFƶOFE JO UIF MJTU EBUBUZQF #FDBVTF JU SFGFS
FODFT UIF MJTU UZQF DPOTUSVDUPS JUTFMG JO UIF TFDPOE BSHV
NFOU JU BMMPXT GPS OFTUJOH PG NVMUJQMF DPOT DFMMT QPTTJCMZ
JOEFƶOJUFMZ XJUI UIF VTF PG SFDVSTJWF GVODUJPOT GPS SFQSF
TFOUJOH BO JOEFƶOJUF OVNCFS PG WBMVFT JO TFSJFT

data [] a = [] | a : [a]
-- ^ cons operator

-- Defining it ourselves

data List a = Nil | Cons a (List a)

-- Creating a list using our list type

Cons 1 (Cons 2 (Cons 3 Nil))

)FSF (Cons 1 ...) (Cons 2 ...) BOE (Cons 3 Nil) BSF BMM
JOEJWJEVBM DPOT DFMMT JO UIF MJTU [1, 2, 3]

 5IF TQJOF JT B XBZ UP SFGFS UP UIF TUSVDUVSF UIBU HMVFT B


DPMMFDUJPO PG WBMVFT UPHFUIFS *O UIF MJTU EBUBUZQF JU JT
GPSNFE CZ UIF SFDVSTJWF OFTUJOH PG DPOT DFMMT 5IF TQJOF JT
JO FTTFODF UIF TUSVDUVSF PG DPMMFDUJPO UIBU JTOƊU UIF WBMVFT
$)"15&3  5)*4 5)*/( "/% 40.& .03& 456'' 

DPOUBJOFE UIFSFJO 0ǒFO TQJOF XJMM CF VTFE JO SFGFSFODF


UP MJTUT CVU JU BQQMJFT XJUI USFF EBUB TUSVDUVSFT BT XFMM

-- Given the list [1, 2, 3]

1 : --------| The nested cons operators


(2 : -----| here represent the spine.
(3 : --|
[]))

-- Blanking the irrelevant values out

_ : ----------|
(_ : -------|
(_ : ----> Spine
[]))

 'PMMPXVQ SFTPVSDFT


 Data.List EPDVNFOUBUJPO GPS UIF base MJCSBSZ
http://hackage.haskell.org/package/base/docs/Data-List.html

 /JOFUZOJOF )BTLFMM QSPCMFNT


https://wiki.haskell.org/H-99:_Ninety-Nine_Haskell_Problems
$IBQUFS 

'PMEJOH MJTUT

5IF FYQMJDJU UFBDIJOH PG


UIJOLJOH JT OP USJWJBM UBTL
CVU XIP TBJE UIBU UIF
UFBDIJOH PG QSPHSBNNJOH
JT *O PVS UFSNJOPMPHZ
UIF NPSF FYQMJDJUMZ
UIJOLJOH JT UBVHIU UIF
NPSF PG B TDJFOUJTU UIF
QSPHSBNNFS XJMM
CFDPNF

&ETHFS %JKLTUSB


$)"15&3  %"5" 4536$563& 03*(".* 

 'PMET
'PMEJOH JT B DPODFQU UIBU FYUFOET JO VTFGVMOFTT BOE JNQPSUBODF
CFZPOE MJTUT CVU MJTUT BSF PǒFO IPX UIFZ BSF JOUSPEVDFE 'PMET
BT B HFOFSBM DPODFQU BSF DBMMFE DBUBNPSQIJTNT :PVƊSF GBNJM
JBS XJUI UIF SPPU ƌNPSQIJTNƍ GSPN QPMZNPSQIJTN ƌ$BUBƍ
NFBOT ƌEPXOƍ PS ƌBHBJOTUƍ BT JO ƌDBUBDPNCTƍ $BUBNPSQIJTNT
BSF B NFBOT PG EFDPOTUSVDUJOH EBUB *G UIF TQJOF PG B MJTU JT UIF
TUSVDUVSF PG B MJTU UIFO B GPME JT XIBU DBO SFEVDF UIBU TUSVDUVSF
5IJT DIBQUFS JT B UIPSPVHI MPPL BU UIF UPQJD PG GPMEJOH MJTUT
JO )BTLFMM 8F XJMM

Ƒ FYQMBJO XIBU GPMET BSF BOE IPX UIFZ XPSL

Ƒ HP JOUP EFUBJM UIF FWBMVBUJPO QSPDFTTFT PG GPMET

Ƒ XBML UISPVHI UIF QSPDFTT PG XSJUJOH GPMEJOH GVODUJPOT

Ƒ JOUSPEVDF TDBOT GVODUJPOT UIBU BSF SFMBUFE UP GPMET

 #SJOHJOH ZPV JOUP UIF GPME


-FUƊT TUBSU XJUI B RVJDL MPPL BU foldr TIPSU GPS ƌGPME SJHIUƍ 5IJT
JT UIF GPME ZPVƊMM NPTU PǒFO XBOU UP VTF XJUI MJTUT 5IF GPMMPX
JOH UZQF TJHOBUVSF NBZ MPPL B MJUUMF IBJSZ CVU MFUƊT DPNQBSF JU

/PUF UIBU B DBUBNPSQIJTN DBO CSFBL EPXO UIF TUSVDUVSF CVU UIBU TUSVDUVSF NJHIU CF
SFCVJMU TP UP TQFBL EVSJOH FWBMVBUJPO 5IBU JT GPMET DBO SFUVSO MJTUT BT SFTVMUT
$)"15&3  %"5" 4536$563& 03*(".* 

UP XIBU XF LOPX BCPVU NBQQJOH /PUF UIBU UIF UZQF PG foldr


NBZ CF EJƵFSFOU JG ZPV IBWF ()$  PS OFXFS

-- GHC 7.8 and older


foldr :: (a -> b -> b) -> b -> [a] -> b

-- GHC 7.10 and newer


foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b

5IFO MJOFE VQ OFYU UP FBDI PUIFS

foldr :: Foldable t =>


(a -> b -> b) -> b -> t a -> b
foldr :: (a -> b -> b) -> b -> [] a -> b

'PS OPX BMM ZPV OFFE UP LOPX JT UIBU ()$  BCTUSBDUFE
PVU UIF MJTUTQFDJƶD QBSU PG GPMEJOH JOUP B UZQFDMBTT UIBU MFUT ZPV
SFVTF UIF TBNF GPMEJOH GVODUJPOT GPS BOZ EBUBUZQF UIBU DBO CF
GPMEFE Ƈ OPU KVTU MJTUT 8F DBO FWFO SFDPWFS UIF NPSF DPODSFUF
UZQF CFDBVTF XF DBO BMXBZT NBLF B UZQF NPSF DPODSFUF CVU
OFWFS NPSF HFOFSJD

Prelude> :t foldr
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
Prelude> :{
*Prelude| let listFoldr = foldr :: (a -> b -> b) ->
*Prelude| b -> [] a -> b
$)"15&3  %"5" 4536$563& 03*(".* 

*Prelude| :}
Prelude> :t listFoldr
listFoldr :: (a -> b -> b) -> b -> [a] -> b

/PX MFUƊT OPUJDF B QBSBMMFM CFUXFFO map BOE foldr

foldr :: (a -> b -> b) -> b -> [a] -> b

-- Remember how map worked?


map :: (a -> b) -> [a] -> [b]
map (+1) 1 : 2 : 3 : []

(+1) 1 : (+1) 2 : (+1) 3 : []

-- Given the list


foldr (+) 0 (1 : 2 : 3 : [])

1 + (2 + (3 + 0))

8IFSF map BQQMJFT B GVODUJPO UP FBDI NFNCFS PG B MJTU BOE


SFUVSOT B MJTU B GPME SFQMBDFT UIF DPOT DPOTUSVDUPST XJUI UIF
GVODUJPO BOE SFEVDFT UIF MJTU

 3FDVSTJWF QBUUFSOT


-FUƊT SFWJTJU sum
$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> sum [1, 5, 10]


16

"T XFƊWF TFFO JU UBLFT B MJTU BEET UIF FMFNFOUT UPHFUIFS


BOE SFUVSOT B TJOHMF SFTVMU :PV NJHIU UIJOL PG JU BT TJNJMBS
UP UIF map GVODUJPOT XFƊWF MPPLFE BU FYDFQU UIBU JUƊT NBQQJOH
(+) PWFS UIF MJTU SFQMBDJOH UIF DPOT PQFSBUPST UIFNTFMWFT BOE
SFUVSOJOH B TJOHMF SFTVMU JOTUFBE PG NBQQJOH GPS FYBNQMF (+1)
JOUP FBDI DPOT DFMM BOE SFUVSOJOH B XIPMF MJTU PG SFTVMUT CBDL
UP VT 5IJT IBT UIF FƵFDU PG CPUI NBQQJOH BO PQFSBUPS PWFS B
MJTU BOE BMTP SFEVDJOH UIF MJTU *O B QSFWJPVT TFDUJPO XF XSPUF
sum JO UFSNT PG SFDVSTJPO

sum :: [Integer] -> Integer


sum [] = 0
sum (x:xs) = x + sum xs

"OE JG XF CSJOH CBDL PVS length GVODUJPO GSPN FBSMJFS

length :: [a] -> Integer


length [] = 0
length (_:xs) = 1 + length xs

%P ZPV TFF TPNF TUSVDUVSBM TJNJMJBSJUZ 8IBU JG ZPV MPPL BU


product BOE concat BT XFMM
$)"15&3  %"5" 4536$563& 03*(".* 

product :: [Integer] -> Integer


product [] = 1
product (x:xs) = x * product xs

concat :: [[a]] -> [a]


concat [] = []
concat (x:xs) = x ++ concat xs

*O FBDI DBTF UIF CBTF DBTF JT UIF JEFOUJUZ GPS UIBU GVODUJPO
4P UIF JEFOUJUZ GPS sum length product BOE concat SFTQFDUJWFMZ
BSF    BOE [] 8IFO XF EP BEEJUJPO BEEJOH [FSP HJWFT VT
UIF TBNF SFTVMU BT PVS JOJUJBM WBMVF 1 + 0 = 1 #VU XIFO XF EP
NVMUJQMJDBUJPO JUƊT NVMUJQMZJOH CZ  UIBU HJWFT VT UIF JEFOUJUZ
2 * 1 = 2 8JUI MJTU DPODBUFOBUJPO UIF JEFOUJUZ JT UIF FNQUZ
MJTU TVDI UIBU [1, 2, 3] ++ [] == [1, 2, 3]
"MTP FBDI PG UIFN IBT B NBJO GVODUJPO XJUI B SFDVSTJWF
QBUUFSO UIBU BTTPDJBUFT UP UIF SJHIU 5IF IFBE PG UIF MJTU HFUT
FWBMVBUFE TFU BTJEF BOE UIFO UIF GVODUJPO NPWFT UP UIF SJHIU
FWBMVBUFT UIF OFYU IFBE BOE TP PO

 'PME SJHIU


8F DBMM foldr UIF ƌSJHIU GPMEƍ CFDBVTF UIF GPME JT SJHIU BTTP
DJBUJWF UIBU JT JU BTTPDJBUFT UP UIF SJHIU 5IJT JT TZOUBDUJDBMMZ
SFƷFDUFE JO B TUSBJHIUGPSXBSE EFƶOJUJPO PG foldr BT XFMM
$)"15&3  %"5" 4536$563& 03*(".* 

foldr :: (a -> b -> b) -> b -> [a] -> b


foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)

5IF TJNJMBSJUJFT CFUXFFO UIJT BOE UIF SFDVSTJWF QBUUFSOT XF


TBX BCPWF TIPVME CF DMFBS 5IF ƌSFTU PG UIF GPME ƍ (foldr f z xs)
JT BO BSHVNFOU UP UIF GVODUJPO f XFƊSF GPMEJOH XJUI 5IF z JT
UIF [FSP PG PVS GPME *U QSPWJEFT B GBMMCBDL WBMVF GPS UIF FNQUZ
MJTU DBTF BOE B TFDPOE BSHVNFOU UP CFHJO PVS GPME XJUI 5IF
[FSP JT PǒFO UIF JEFOUJUZ GPS XIBUFWFS GVODUJPO XFƊSF GPMEJOH
XJUI TVDI BT 0 GPS (+) BOE 1 GPS (*)

)PX GPMES FWBMVBUFT


8FƊSF HPJOH UP SFKJHHFS PVS EFƶOJUJPO PG foldr B MJUUMF CJU *U
XPOƊU DIBOHF UIF TFNBOUJDT CVU JUƊMM NBLF JU FBTJFS UP XSJUF PVU
XIBUƊT IBQQFOJOH

foldr :: (a -> b -> b) -> b -> [a] -> b


foldr f z xs =
case xs of
[] -> z
(x:xs) -> f x (foldr f z xs)

)FSF XF TFF IPX UIF SJHIU GPME BTTPDJBUFT UP UIF SJHIU 5IJT
XJMM SFEVDF KVTU MJLF UIF sum FYBNQMF GSPN FBSMJFS
$)"15&3  %"5" 4536$563& 03*(".* 

-- we're reducing:
foldr (+) 0 [1, 2, 3]

-- First step, what's ``xs'' in our case expression?


foldr (+) 0 [1, 2, 3] =
case [1, 2, 3] of
...

-- What case of the expression matches?


foldr (+) 0 [1, 2, 3] =
case [1, 2, 3] of
[] -> 0
(x:xs) -> f x (foldr f z xs) --<--- this one

-- What are f, x, xs, and z in that


-- branch of the case?
foldr (+) 0 [1, 2, 3] =
case [1, 2, 3] of
[] -> 0
(1 : [2, 3]) -> (+) 1 (foldr (+) 0 [2, 3])

$SJUJDBMMZ XFƊSF HPJOH UP FYQBOE (foldr (+) 0 [2, 3]) POMZ


CFDBVTF (+) JT TUSJDU JO CPUI PG JUT BSHVNFOUT TP JU GPSDFT UIF
OFYU JUFSBUJPO 8F DPVME IBWF B GVODUJPO XIJDI EPFTOƊU DPOUJO
VBMMZ GPSDF UIF SFTU PG UIF GPME *G JU XFSF UP TUPQ PO UIF ƶSTU DBTF
$)"15&3  %"5" 4536$563& 03*(".* 

IFSF UIFO JU XPVMEƊWF SFUVSOFE UIF WBMVF  0OF TVDI GVODUJPO


JT const XIJDI BMXBZT SFUVSOT UIF ƶSTU BSHVNFOU 8FƊMM TIPX
ZPV IPX UIBU CFIBWFT JO B CJU 0VS OFYU SFDVSTJPO JT UIF GPMES

 < >


-- there is (+) 1 implicitly wrapped around this


-- continuation of the recursive fold

foldr (+) 0 [2, 3] =


case [2, 3] of
[] -> 0 -- this didn't match again
(2 : [3]) -> (+) 2 (foldr (+) 0 [3])

(+) JT OPU POMZ TUSJDU JO CPUI PG JUT BSHVNFOUT CVU JUƊT VODPO
EJUJPOBMMZ TP TP XFƊSF HPJOH UP QSPDFFE UP UIF OFYU SFDVSTJPO PG
foldr /PUF UIBU UIF GVODUJPO DBMMT CPVODF CFUXFFO PVS GPME
JOH GVODUJPO f BOE foldr 5IJT CPVODJOH CBDL BOE GPSUI HJWFT
NPSF DPOUSPM UP UIF GPMEJOH GVODUJPO " IZQPUIFUJDBM GPMEJOH
GVODUJPO TVDI BT const XIJDI EPFTOƊU OFFE UIF TFDPOE BSHV
NFOU IBT UIF PQQPSUVOJUZ UP EP MFTT XPSL CZ OPU FWBMVBUJOH JUT
TFDPOE BSHVNFOU XIJDI JT ƌNPSF PG UIF GPMEƍ
$)"15&3  %"5" 4536$563& 03*(".* 

-- there is (+) 1 ((+) 2 ...) implicitly wrapped


-- around this continuation of the recursive fold

-- Next recursion.
foldr (+) 0 [3] =
case [3] of
[] -> 0 -- this didn't match again
(3 : []) -> (+) 3 (foldr (+) 0 [])

8FƊSF HPJOH UP BTL GPS NPSF foldr POF MBTU UJNF BOE UIFO
XFƊMM IJU PVS CBTF DBTF

-- there is (+) 1 ((+) 2 ((+) 3 ...))


-- implicitly wrapped around this continuation
-- of the recursive fold

-- Last recursion, this is the end of the spine.


foldr (+) 0 [] =
case [] of
[] -> 0 --<-- This one finally matches.
-- ignore the other case, didn't happen.

4P POF XBZ UP UIJOL BCPVU UIF XBZ )BTLFMM FWBMVBUFT JT UIBU


JUƊT MJLF B UFYU SFXSJUJOH TZTUFN 0VS FYQSFTTJPO IBT UIVT GBS
SFXSJUUFO JUTFMG GSPN

foldr (+) 0 [1, 2, 3]


$)"15&3  %"5" 4536$563& 03*(".* 

*OUP

(+) 1 ((+) 2 ((+) 3 0))

*G ZPV XBOUFE UP DMFBO JU VQ B CJU XJUIPVU DIBOHJOH IPX JU


FWBMVBUFT ZPV DPVME NBLF JU UIF GPMMPXJOH

1 + (2 + (3 + 0))

+VTU MJLF JO BSJUINFUJD XF FWBMVBUF JOOFSNPTU QBSFOUIFTFT


ƶSTU

1 + (2 + (3 + 0))

1 + (2 + 3)

1 + 5

"OE OPX XFƊSF EPOF XJUI UIF SFTVMU PG 


8F DBO BMTP VTF B USJDL QPQVMBSJ[FE CZ TPNF IFMQGVM VTFST
JO UIF )BTLFMM *3$ DPNNVOJUZ UP TFF IPX UIF GPME BTTPDJBUFT

Prelude> let xs = map show [1..5]


Prelude> :{

*EFB CPSSPXFE GSPN $BMF (JCCBSE GSPN UIF IBTLFMM 'SFFOPEF *3$ DIBOOFM BOE PO
UIF )BTLFMMPSH XJLJ https://wiki.haskell.org/Fold#Examples
$)"15&3  %"5" 4536$563& 03*(".* 

*Prelude| foldr (\x y -> concat ["(",x,"+",y,")"])


*Prelude| "0" xs
*Prelude| :}
"(1+(2+(3+(4+(5+0)))))"

0OF JOJUJBMMZ OPOPCWJPVT BTQFDU PG GPMEJOH JT UIBU JU IBQ


QFOT JO UXP TUBHFT USBWFSTBM BOE GPMEJOH 5SBWFSTBM JT UIF TUBHF
JO XIJDI UIF GPME SFDVSTFT PWFS UIF TQJOF 'PMEJOH SFGFST UP UIF
FWBMVBUJPO PS SFEVDUJPO PG UIF GPMEJOH GVODUJPO BQQMJFE UP UIF
WBMVFT "MM GPMET SFDVSTF PWFS UIF TQJOF JO UIF TBNF EJSFDUJPO
UIF EJƵFSFODF CFUXFFO MFǒ GPMET BOE SJHIU GPMET JT JO UIF BTTP
DJBUJPO PS QBSFOUIFTJ[BUJPO PG UIF GPMEJOH GVODUJPO BOE UIVT
XIJDI EJSFDUJPO UIF GPMEJOH PS SFEVDUJPO QSPDFFET
8JUI foldr UIF SFTU PG PVS GPME JT BO BSHVNFOU UP UIF GVOD
UJPO XFƊSF GPMEJOH XJUI

foldr f z (x:xs) = f x (foldr f z xs)


-- ^--------------^
-- rest of the fold

(JWFO UIJT UXPTUBHF QSPDFTT BOE OPOTUSJDU FWBMVBUJPO JG


ԕ EPFTOƊU FWBMVBUF JUT TFDPOE BSHVNFOU SFTU PG UIF GPME
OP
NPSF PG UIF TQJOF XJMM CF GPSDFE 0OF PG UIF DPOTFRVFODFT PG
UIJT JT UIBU foldr DBO BWPJE FWBMVBUJOH OPU KVTU TPNF PS BMM PG
UIF WBMVFT JO UIF MJTU CVU TPNF PS BMM PG UIF MJTUƊT TQJOF BT XFMM
'PS UIJT SFBTPO foldr DBO CF VTFE XJUI MJTUT UIBU BSF QPUFOUJBMMZ
JOƶOJUF 'PS FYBNQMF DPNQBSF UIF GPMMPXJOH TFUT PG SFTVMUT
$)"15&3  %"5" 4536$563& 03*(".* 

-- (+) will unconditionally evaluate the entire


-- spine and all of the values
Prelude> foldr (+) 0 [1..5]
15

(JWFO UIBU ZPV IBWF UIF GVODUJPO myAny

myAny :: (a -> Bool) -> [a] -> Bool


myAny f xs =
foldr (\x b -> f x || b) False xs

5IF GPMMPXJOH TIPVME XPSL EFTQJUF CFJOH BO JOƶOJUF MJTU

Prelude> myAny even [1..]


True

5IF GPMMPXJOH XJMM OFWFS ƶOJTI FWBMVBUJOH CFDBVTF JUƊT BMXBZT


BO PEE OVNCFS

Prelude> myAny even (repeat 1)

"OPUIFS UFSN XF VTF GPS UIJT OFWFSFOEJOH FWBMVBUJPO JT


CPUUPN PS undefined 5IFSFƊT OP HVBSBOUFF UIBU B GPME PG BO
JOƶOJUF MJTU XJMM ƶOJTI FWBMVBUJOH FWFO JG ZPV VTFE foldr JU PG
UFO EFQFOET PO UIF JOQVU EBUB BOE UIF GPME GVODUJPO -FU VT
DPOTJEFS TPNF NPSF FYBNQMFT XJUI B MFTT JODPOWFOJFOU CPUUPN
$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> let u = undefined

-- here, we give an undefined value


Prelude> foldr (+) 0 [1, 2, 3, 4, u]
*** Exception: Prelude.undefined

Prelude> foldr (+) 0 (take 4 [1, 2, 3, 4, u])


10

-- here, the undefined is part of the spine


Prelude> foldr (+) 0 ([1, 2, 3, 4] ++ u)
*** Exception: Prelude.undefined
Prelude> foldr (+) 0 (take 4 ([1, 2, 3, 4] ++ u))
10

#Z UBLJOH POMZ UIF ƶSTU GPVS FMFNFOUT XF TUPQ UIF SFDVSTJWF


GPMEJOH QSPDFTT BU KVTU UIF ƶSTU GPVS WBMVFT TP PVS BEEJUJPO
GVODUJPO EPFT OPU SVO JOUP CPUUPN BOE UIBU XPSLT XIFUIFS
undefined JT POF PG UIF WBMVFT PS QBSU PG UIF TQJOF
5IF length GVODUJPO CFIBWFT EJƵFSFOUMZ JU FWBMVBUFT UIF
TQJOF VODPOEJUJPOBMMZ CVU OPU UIF WBMVFT

Prelude> length [1, 2, 3, 4, undefined]


5
Prelude> length ([1, 2, 3, 4] ++ undefined)
*** Exception: Prelude.undefined
$)"15&3  %"5" 4536$563& 03*(".* 

)PXFWFS JG XF ESPQ UIF QBSU PG UIF TQJOF UIBU JODMVEFT UIF


CPUUPN CFGPSF XF VTF length XF DBO HFU BO FYQSFTTJPO UIBU
XPSLT

Prelude> length (take 4 ([1, 2, 3, 4] ++ undefined))


4

take JT OPOTUSJDU MJLF FWFSZUIJOH FMTF ZPVƊWF TFFO TP GBS BOE


JO UIJT DBTF JU POMZ SFUVSOT BT NVDI MJTU BT ZPV BTL GPS 5IF EJG
GFSFODF JO XIBU JU EPFT JT JU TUPQT SFUVSOJOH FMFNFOUT PG UIF MJTU
JU XBT HJWFO XIFO JU IJUT UIF MFOHUI MJNJU ZPV HBWF JU $POTJEFS
UIJT

Prelude> length $ take 2 $ take 4 ([1, 2]++undefined)


2

*U EPFTOƊU NBUUFS UIBU take 4 DPVMEƊWF IJU UIF CPUUPN /PUIJOH


GPSDFE JU UP CFDBVTF PG UIF take 2 CFUXFFO JU BOE MFOHUI
/PX UIBU XFƊWF TFFO IPX UIF SFDVSTJWF TFDPOE BSHVNFOU UP
foldrƊT GPMEJOH GVODUJPO XPSLT MFUƊT DPOTJEFS UIF ƶSTU BSHVNFOU

foldr :: (a -> b -> b) -> b -> [a] -> b


foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
-- [1]

5IF ƶSTU BSHVNFOU [1] JOWPMWFT B QBUUFSO NBUDI UIBU JT TUSJDU


CZ EFGBVMU Ƈ UIF f POMZ BQQMJFT UP x JG UIFSF JT BO x WBMVF BOE
$)"15&3  %"5" 4536$563& 03*(".* 

OPU KVTU BO FNQUZ MJTU 5IJT NFBOT UIBU foldr NVTU GPSDF BO
JOJUJBM DPOT DFMM JO PSEFS UP EJTDSJNJOBUF CFUXFFO UIF [] BOE
UIF (x : xs) DBTFT TP UIF ƶSTU DPOT DFMM DBOOPU CF VOEFƶOFE
/PX XFƊSF HPJOH UP USZ TPNFUIJOH VOVTVBM UP EFNPOTUSBUF
UIBU UIF ƶSTU CJU PG UIF TQJOF NVTU CF FWBMVBUFE CZ foldr 8F
IBWF B TPNFXIBU TJMMZ BOPOZNPVT GVODUJPO UIBU XJMM JHOPSF BMM
JUT BSHVNFOUT BOE KVTU SFUVSO B WBMVF PG  8FƊSF VTJOH JU
XJUI foldr CFDBVTF JU XJMM OFWFS GPSDF FWBMVBUJPO PG BOZ PG JUT
BSHVNFOUT TP XF DBO IBWF B CPUUPN BT B WBMVF PS BT QBSU PG
UIF TQJOF BOE JU XJMM OPU GPSDF BO FWBMVBUJPO

Prelude> foldr (\_ _ -> 9001) 0 [1..5]


9001
Prelude> foldr (\_ _ -> 9001) 0 [1, 2, 3, undefined]
9001
Prelude> foldr (\_ _ -> 9001) 0 ([1, 2, 3] ++ undefined)
9001

&WFSZUIJOH JT ƶOF VOMFTT UIF ƶSTU QJFDF PG UIF TQJOF JT CPU


UPN

Prelude> foldr (\_ _ -> 9001) 0 undefined


*** Exception: Prelude.undefined

Prelude> foldr (\_ _ -> 9001) 0 [1, undefined]


9001
Prelude> foldr (\_ _ -> 9001) 0 [undefined, undefined]
$)"15&3  %"5" 4536$563& 03*(".* 

9001

5IF ƶOBM UXP FYBNQMFT XPSL CFDBVTF JU JTOƊU UIF ƶSTU DPOT
DFMM UIBU JT CPUUPN ƈ UIF VOEFƶOFE WBMVFT BSF JOTJEF UIF DPOT
DFMMT OPU JO UIF TQJOF JUTFMG 1VU EJƵFSFOUMZ UIF DPOT DFMMT
DPOUBJO CPUUPN WBMVFT CVU BSF OPU UIFNTFMWFT CPUUPN 8F XJMM
FYQFSJNFOU MBUFS XJUI OPOTUSJDUOFTT BOE TUSJDUOFTT UP TFF IPX
JU BƵFDUT UIF XBZ PVS QSPHSBNT FWBMVBUF
5SBWFSTJOH UIF SFTU PG UIF TQJOF EPFTOƊU PDDVS VOMFTT UIF
GVODUJPO BTLT GPS UIF SFTVMUT PG IBWJOH GPMEFE UIF SFTU PG UIF MJTU
*O UIF GPMMPXJOH FYBNQMFT XF EPOƊU GPSDF USBWFSTBM PG UIF TQJOF
CFDBVTF const KVTU UISPXT BXBZ JUT TFDPOE BSHVNFOU XIJDI JT
UIF SFTU PG UIF GPME

-- reminder:
-- const :: a -> b -> a
-- const x _ = x

Prelude> const 1 2
1
Prelude> const 2 1
2
Prelude> foldr const 0 [1..5]
1
Prelude> foldr const 0 [1, undefined]
1
$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> foldr const 0 ([1, 2] ++ undefined)


1
Prelude> foldr const 0 [undefined, 2]
*** Exception: Prelude.undefined

/PX UIBU XFƊWF TFFO IPX foldr FWBMVBUFT XFƊSF HPJOH UP


MPPL BU foldl CFGPSF XF NPWF PO UP MFBSOJOH IPX UP XSJUF BOE
VTF GPMET

 'PME MFǒ


#FDBVTF PG UIF XBZ MJTUT XPSL GPMET NVTU ƶSTU SFDVSTF PWFS
UIF TQJOF PG UIF MJTU GSPN UIF CFHJOOJOH UP UIF FOE -Fǒ GPMET
USBWFSTF UIF TQJOF JO UIF TBNF EJSFDUJPO BT SJHIU GPMET CVU UIFJS
GPMEJOH QSPDFTT JT MFǒ BTTPDJBUJWF BOE QSPDFFET JO UIF PQQPTJUF
EJSFDUJPO BT UIBU PG foldr
)FSFƊT B TJNQMF EFƶOJUJPO PG foldl /PUF UIBU UP TFF UIF TBNF
UZQF GPS foldl JO ZPVS ()$J 3&1- ZPV XJMM OFFE UP JNQPSU
Data.List GPS UIF TBNF SFBTPOT BT XJUI foldr

-- again, different type in GHC 7.10 and newer.

foldl :: (b -> a -> b) -> b -> [a] -> b


foldl f acc [] = acc
foldl f acc (x:xs) = foldl f (f acc x) xs
$)"15&3  %"5" 4536$563& 03*(".* 

foldl :: (b -> a -> b) -> b -> [a] -> b

-- Given the list


foldl (+) 0 (1 : 2 : 3 : [])

-- foldl associates like so


((0 + 1) + 2) + 3

8F DBO BMTP VTF UIF TBNF USJDL XF VTFE UP TFF UIF BTTPDJB
UJWJUZ PG foldr UP TFF UIF BTTPDJBUJWJUZ PG foldl

Prelude> let f = (\x y -> concat ["(",x,"+",y,")"])

Prelude> foldl f "0" (map show [1..5])


"(((((0+1)+2)+3)+4)+5)"

8F DBO TFF GSPN UIJT UIBU foldl CFHJOT JUT SFEVDUJPO QSPDFTT
CZ BEEJOH UIF acc BDDVNVMBUPS
WBMVF UP UIF IFBE PG UIF MJTU
XIFSFBT foldr IBE BEEFE JU UP UIF ƶOBM FMFNFOU PG UIF MJTU ƶSTU
8F DBO BMTP VTF GVODUJPOT DBMMFE TDBOT UP TFF IPX GPMET FWBM
VBUF 4DBOT BSF TJNJMBS UP GPMET CVU SFUVSO B MJTU PG BMM UIF JOUFS
NFEJBUF TUBHFT PG UIF GPME 8F DBO DPNQBSF scanr BOE scanl UP
UIFJS BDDPNQBOZJOH GPMET UP TFF UIF EJƵFSFODF JO FWBMVBUJPO

Prelude> foldr (+) 0 [1..5]


15
Prelude> scanr (+) 0 [1..5]
$)"15&3  %"5" 4536$563& 03*(".* 

[15,14,12,9,5,0]

Prelude> foldl (+) 0 [1..5]


15
Prelude> scanl (+) 0 [1..5]
[0,1,3,6,10,15]

5IF SFMBUJPOTIJQ CFUXFFO UIF TDBOT BOE GPMET BSF BT GPMMPXT

last (scanl f z xs) = foldl f z xs


head (scanr f z xs) = foldr f z xs

&BDI GPME XJMM SFUVSO UIF TBNF SFTVMU GPS UIJT PQFSBUJPO CVU
XF DBO TFF GSPN UIF TDBOT UIBU UIFZ BSSJWF BU UIBU SFTVMU JO B
EJƵFSFOU PSEFS EVF UP UIF EJƵFSFOU BTTPDJBUJWJUZ 8FƊMM UBML
NPSF BCPVU TDBOT MBUFS

"TTPDJBUJWJUZ BOE GPMEJOH


/FYU XFƊMM UBLF B DMPTFS MPPL BU TPNF PG UIF FƵFDUT PG UIF BTTP
DJBUJWJUZ PG foldl "T XFƊWF TBJE CPUI GPMET USBWFSTF UIF TQJOF
JO UIF TBNF EJSFDUJPO 8IBUƊT EJƵFSFOU JT UIF BTTPDJBUJWJUZ PG
UIF FWBMVBUJPO
5IF GVOEBNFOUBM XBZ UP UIJOL BCPVU FWBMVBUJPO JO )BTLFMM
JT BT TVCTUJUVUJPO 8IFO XF VTF B SJHIU GPME PO B MJTU XJUI UIF
GVODUJPO ԕ BOE TUBSU WBMVF ԩ XFƊSF JO B TFOTF SFQMBDJOH UIF
DPOT DPOTUSVDUPST XJUI PVS GPMEJOH GVODUJPO BOE UIF FNQUZ MJTU
DPOTUSVDUPS XJUI PVS TUBSU WBMVF ԩ
$)"15&3  %"5" 4536$563& 03*(".* 

[1..3] == 1 : 2 : 3 : []

foldr f z [1, 2, 3]
1 `f` (foldr f z [2, 3])
1 `f` (2 `f` (foldr f z [3]))
1 `f` (2 `f` (3 `f` (foldr f z [])))
1 `f` (2 `f` (3 `f` z))

'VSUIFSNPSF MB[Z FWBMVBUJPO MFUT PVS GVODUJPOT SBUIFS UIBO


UIF BNCJFOU TFNBOUJDT PG UIF MBOHVBHF EJDUBUF XIBU PSEFS
UIJOHT HFU FWBMVBUFE JO #FDBVTF PG UIJT UIF QBSFOUIFTFT BSF SFBM
*O UIF BCPWF UIF 3 `f` z QBJSJOH HFUT FWBMVBUFE ƶSTU CFDBVTF
JUƊT JO UIF JOOFSNPTU QBSFOUIFTFT 3JHIU GPMET IBWF UP USBWFSTF
UIF MJTU PVUTJEFJO CVU UIF GPMEJOH JUTFMG TUBSUT GSPN UIF FOE PG
UIF MJTU
*UƊT IBSE UP TFF UIJT XJUI BSJUINFUJD GVODUJPOT UIBU BSF BT
TPDJBUJWF TVDI BT BEEJUJPO CVU JUƊT BO JNQPSUBOU QPJOU UP VO
EFSTUBOE TP XFƊMM SVO UISPVHI TPNF EJƵFSFOU FYBNQMFT -FUƊT
TUBSU CZ VTJOH BO BSJUINFUJD PQFSBUJPO UIBU JTOƊU BTTPDJBUJWF

Prelude> foldr (^) 2 [1..3]


1
Prelude> foldl (^) 2 [1..3]
64

5IJT UJNF XF DBO TFF DMFBSMZ UIBU XF HPU EJƵFSFOU SFTVMUT BOE
$)"15&3  %"5" 4536$563& 03*(".* 

UIBU EJƵFSFODF SFTVMUT GSPN UIF XBZ UIF GVODUJPOT BTTPDJBUF


)FSFƊT B CSFBLEPXO

-- if you want to follow along,


-- use paper and not the REPL.
foldr (^) 2 [1..3]
(1 ^ (2 ^ (3 ^ 2)))
(1 ^ (2 ^ 9))
1 ^ 512
1

$POUSBTU UIBU XJUI UIJT

foldl (^) 2 [1..3]


((2 ^ 1) ^ 2) ^ 3
(2 ^ 2) ^ 3
4 ^ 3
64

*O UIJT OFYU TFU PG DPNQBSJTPOT XF XJMM EFNPOTUSBUF UIF


FƵFDU PG BTTPDJBUJWJUZ PO BSHVNFOU PSEFS CZ GPMEJOH UIF MJTU
JOUP B OFX MJTU MJLF UIJT

Prelude> foldr (:) [] [1..3]


[1,2,3]
Prelude> foldl (flip (:)) [] [1..3]
[3,2,1]
$)"15&3  %"5" 4536$563& 03*(".* 

8F NVTU VTF flip XJUI foldl -FUƊT FYBNJOF XIZ


+VTU MJLF B SJHIU GPME B MFǒ GPME DBOOPU QFSGPSN NBHJD BOE HP
UP UIF FOE PG UIF MJTU JOTUBOUMZ JU NVTU TUBSU GSPN UIF CFHJOOJOH
PG UIF MJTU )PXFWFS UIF QBSFOUIFTFT EJDUBUF IPX PVS DPEF
FWBMVBUFT 5IF UZQF PG UIF BSHVNFOU UP UIF GPMEJOH GVODUJPO
DIBOHFT JO BEEJUJPO UP UIF BTTPDJBUJWJUZ

foldr :: (a -> b -> b) -> b -> [a] -> b


-- [1] [2] [3]
foldl :: (b -> a -> b) -> b -> [a] -> b
-- [4] [5] [6]

 5IF QBSBNFUFS PG UZQF Ԑ SFQSFTFOUT POF PG UIF MJTU FMFNFOU


BSHVNFOUT UIF GPMEJOH GVODUJPO PG foldr JT BQQMJFE UP

 5IF QBSBNFUFS PG UZQF ԑ XJMM FJUIFS CF UIF TUBSU WBMVF PS


UIF SFTVMU PG UIF GPME BDDVNVMBUFE TP GBS EFQFOEJOH PO
IPX GBS ZPV BSF JOUP UIF GPME

 5IF ƶOBM SFTVMU PG IBWJOH DPNCJOFE UIF MJTU FMFNFOU BOE


UIF TUBSU WBMVF PS GPME TP GBS UP DPNQVUF UIF GPME

 5IF TUBSU WBMVF PS GPME BDDVNVMBUFE TP GBS JT UIF ƶSTU BS


HVNFOU UP foldlƊT GPMEJOH GVODUJPO

 5IF MJTU FMFNFOU JT UIF TFDPOE BSHVNFOU UP foldlƊT GPMEJOH


GVODUJPO
$)"15&3  %"5" 4536$563& 03*(".* 

 5IF ƶOBM SFTVMU PG foldlƊT GPME GVODUJPO JT PG UZQF ԑ KVTU MJLF


UIBU PG foldr

5IF UZQF PG (:) SFRVJSFT UIBU B WBMVF CF UIF ƶSTU BSHVNFOU


BOE B MJTU CF UIF TFDPOE BSHVNFOU

(:) :: a -> [a] -> [a]

4P UIF WBMVF JT QSFQFOEFE PS ƌDPOTFE POUP ƍ UIF GSPOU PG


UIBU MJTU
*O UIF GPMMPXJOH FYBNQMFT UIF UJMEF NFBOT ƌJT FRVJWBMFOU PS
FRVBM UPƍ *G XF XSJUF B SJHIU GPME UIBU IBT UIF DPOT DPOTUSVDUPS
BT PVS ԕ BOE UIF FNQUZ MJTU BT PVS ԩ XF HFU

-- foldr f z [1, 2, 3]
-- f ~ (:); z ~ []
-- Run it in your REPL. It'll return True.
foldr (:) [] (1 : 2 : 3 : []) == 1 : (2 : (3 : []))

5IF DPOTJOH QSPDFTT GPS foldr NBUDIFT UIF UZQF TJHOBUVSF


GPS (:) *U BMTP SFQSPEVDFT UIF TBNF MJTU CFDBVTF XFƊSF SFQMBDJOH
UIF DPOT DPOTUSVDUPST XJUI DPOT DPOTUSVDUPST BOE UIF OVMM MJTU
XJUI OVMM MJTU )PXFWFS GPS JU UP CF JEFOUJDBM JU BMTP IBT UP CF
SJHIU BTTPDJBUJWF
%PJOH UIF TBNF XJUI foldl EPFT OPU QSPEVDF UIF TBNF SFTVMU
8IFO VTJOH foldl UIF SFTVMU XFƊWF BDDVNVMBUFE TP GBS JT UIF
ƶSTU BSHVNFOU JOTUFBE PG UIF MJTU FMFNFOU 5IJT JT PQQPTJUF PG
$)"15&3  %"5" 4536$563& 03*(".* 

XIBU (:) FYQFDUT JG XFƊSF BDDVNVMBUJOH B MJTU 5SZJOH UP GPME


UIF JEFOUJUZ PG UIF MJTU BT BCPWF CVU XJUI foldl XPVME HJWF VT B
UZQF FSSPS CFDBVTF UIF SFDPOTUSVDUJOH QSPDFTT GPS foldl XPVME
MPPL MJLF UIJT

foldl f z [1, 2, 3]
-- f ~ (:); z ~ []
-- (((z `f` 1) `f` 2) `f` 3)
((([] : 1) : 2) : 3)

5IBU XPOƊU XPSL CFDBVTF UIF ԩ JT BO FNQUZ MJTU BOE UIF ԕ JT


DPOT TP XF IBWF UIF PSEFS PG BSHVNFOUT CBDLXBSET GPS DPOT
&OUFS flip XIPTF KPC JT UP UBLF CBDLXBSET BSHVNFOUT BOE UVSO
UIBU GSPXO VQTJEF EPXO *U XJMM ƷJQ FBDI TFU PG BSHVNFOUT
BSPVOE GPS VT MJLF UIJT

foldl f z [1, 2, 3]
-- f ~ (flip (:)); z ~ []
-- (((z `f` 1) `f` 2) `f` 3)
f = flip (:)
((([] `f` 1) `f` 2) `f` 3)
(([1] `f` 2) `f` 3)
([2, 1] `f` 3)
[3, 2, 1]
$)"15&3  %"5" 4536$563& 03*(".* 

&WFO XIFO XFƊWF TBUJTƶFE UIF UZQFT CZ ƷJQQJOH UIJOHT BSPVOE


UIF MFǒBTTPDJBUJOH OBUVSF PG foldl MFBET UP B EJƵFSFOU SFTVMU
GSPN UIBU PG foldr
'PS UIF OFYU TFU PG DPNQBSJTPOT XFƊSF HPJOH UP VTF B GVOD
UJPO DBMMFE const UIBU UBLFT UXP BSHVNFOUT BOE BMXBZT SFUVSOT
UIF ƶSTU POF 8IFO XF GPME const PWFS B MJTU JU XJMM UBLF BT JUT
ƶSTU QBJS PG BSHVNFOUT UIF acc WBMVF BOE B WBMVF GSPN UIF MJTU
ƈ XIJDI WBMVF JU UBLFT ƶSTU EFQFOET PO XIJDI UZQF PG GPME JU JT
8FƊMM TIPX ZPV IPX JU FWBMVBUFT GPS UIF ƶSTU FYBNQMF

Prelude> foldr const 0 [1..5]


(const 1 _)
1

4JODF const EPFTOƊU FWBMVBUF JUT TFDPOE BSHVNFOU UIF SFTU PG


UIF GPME JT OFWFS FWBMVBUFE 5IF VOEFSTDPSF SFQSFTFOUT UIF SFTU
PG UIF VOFWBMVBUFE GPME /PX MFUƊT MPPL BU UIF FƵFDU PG ƷJQQJOH
UIF BSHVNFOUT 5IF 0 SFTVMU JT CFDBVTF [FSP JT PVS BDDVNVMBUPS
WBMVF IFSF TP JUƊT UIF ƶSTU PS MBTU
WBMVF PG UIF MJTU

Prelude> foldr (flip const) 0 [1..5]


0

/FYU MFUƊT MPPL BU XIBU IBQQFOT XIFO XF VTF UIF TBNF GVOD
UJPOT CVU UIJT UJNF XJUI foldl 5BLF B GFX NPNFOUT UP VOEFS
TUBOE UIF FWBMVBUJPO QSPDFTT UIBU MFBET UP UIFTF SFTVMUT
$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> foldl (flip const) 0 [1..5]


5
Prelude> foldl const 0 [1..5]
0

5IJT JT UIF FƵFDU PG MFǒ BTTPDJBUJWJUZ 5IF TQJOF USBWFSTBM


IBQQFOT JO UIF TBNF PSEFS JO B MFǒ PS SJHIU GPME ƈ JU NVTU
CFDBVTF PG UIF XBZ MJTUT BSF EFƶOFE *G ZPVS GPMEJOH GVODUJPO
JTOƊU DPNNVUBUJWF B MFǒ GPME DBO MFBE UP B EJƵFSFOU SFTVMU UIBO
B SJHIU GPME PG UIF TBNF

&YFSDJTFT 6OEFSTUBOEJOH 'PMET


 foldr (*) 1 [1..5]

XJMM SFUVSO UIF TBNF SFTVMU BT XIJDI PG UIF GPMMPXJOH

B
flip (*) 1 [1..5]
C
foldl (flip (*)) 1 [1..5]
D
foldl (*) 1 [1..5]

 8SJUF PVU UIF FWBMVBUJPO TUFQT GPS

foldl (flip (*)) 1 [1..3]

 0OF EJƵFSFODF CFUXFFO foldr BOE foldl JT

B
foldr CVU OPU foldl USBWFSTFT UIF TQJOF PG B MJTU GSPN
SJHIU UP MFǒ
$)"15&3  %"5" 4536$563& 03*(".* 

C
foldr CVU OPU foldl BMXBZT GPSDFT UIF SFTU PG UIF GPME
D
foldr CVU OPU foldl BTTPDJBUFT UP UIF SJHIU
E
foldr CVU OPU foldl JT SFDVSTJWF

 'PMET BSF DBUBNPSQIJTNT XIJDI NFBOT UIFZ BSF HFOFSBMMZ


VTFE UP

B
SFEVDF TUSVDUVSF
C
FYQBOE TUSVDUVSF
D
SFOEFS ZPV DBUBUPOJD
E
HFOFSBUF JOƶOJUF EBUB TUSVDUVSFT

 5IF GPMMPXJOH BSF TJNQMF GPMET WFSZ TJNJMBS UP XIBU ZPVƊWF


BMSFBEZ TFFO CVU FBDI IBT BU MFBTU POF FSSPS 1MFBTF ƶY
UIFN BOE UFTU JO ZPVS 3&1-

B
foldr (++) ["woot", "WOOT", "woot"]

C
foldr max [] "fear is the little death"

D
foldr and True [False, True]

E
5IJT POF JT NPSF TVCUMF UIBO UIF QSFWJPVT $BO JU FWFS
SFUVSO B EJƵFSFOU BOTXFS

foldr (||) True [False, True]

F
foldl ((++) . show) "" [1..5]

G
foldr const 'a' [1..5]
$)"15&3  %"5" 4536$563& 03*(".* 

H
foldr const 0 "tacos"

I
foldl (flip const) 0 "burritos"

J
foldl (flip const) 'z' [1..5]

6ODPOEJUJPOBM TQJOF SFDVSTJPO


"O JNQPSUBOU EJƵFSFODF CFUXFFO foldr BOE foldl JT UIBU B MFǒ
GPME IBT UIF TVDDFTTJWF TUFQT PG UIF GPME BT JUT ƶSTU BSHVNFOU
5IF OFYU SFDVSTJPO PG UIF TQJOF JTOƊU JOUFSNFEJBUFE CZ UIF
GPMEJOH GVODUJPO BT JU JT JO foldr XIJDI BMTP NFBOT SFDVSTJPO PG
UIF TQJOF JT VODPOEJUJPOBM )BWJOH B GVODUJPO UIBU EPFTOƊU GPSDF
FWBMVBUJPO PG FJUIFS PG JUT BSHVNFOUT XPOƊU DIBOHF BOZUIJOH
-FUƊT SFWJFX const

Prelude> const 1 undefined


1
Prelude> (flip const) 1 undefined
*** Exception: Prelude.undefined
Prelude> (flip const) undefined 1
1

/PX DPNQBSF

Prelude> foldr const 0 ([1..5] ++ undefined)


1
Prelude> foldr (flip const) 0 ([1..5] ++ undefined)
*** Exception: Prelude.undefined
$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> foldl const 0 ([1..5] ++ undefined)


*** Exception: Prelude.undefined
Prelude> foldl (flip const) 0 ([1..5] ++ undefined)
*** Exception: Prelude.undefined

)PXFWFS XIJMF foldl VODPOEJUJPOBMMZ FWBMVBUFT UIF TQJOF


ZPV DBO TUJMM TFMFDUJWFMZ FWBMVBUF UIF WBMVFT JO UIF MJTU

Prelude> foldl (\_ _ -> 5) 0 ([1..5] ++ undefined)


*** Exception: Prelude.undefined
-- error because bottom is part of the spine
-- and foldl must evaluate the spine

Prelude> foldl (\_ _ -> 5) 0 ([1..5] ++ [undefined])


5
-- this is OK because here bottom is a value

5IJT GFBUVSF NFBOT UIBU foldl JT HFOFSBMMZ JOBQQSPQSJBUF


XJUI MJTUT UIBU BSF PS DPVME CF JOƶOJUF CVU UIF DPNCJOBUJPO PG
UIF GPSDFE TQJOF FWBMVBUJPO XJUI OPOTUSJDUOFTT NFBOT UIBU JU JT
BMTP VTVBMMZ JOBQQSPQSJBUF FWFO GPS MPOH MJTUT BT UIF GPSDFE FWBM
VBUJPO PG UIF TQJOF BƵFDUT QFSGPSNBODF OFHBUJWFMZ #FDBVTF
foldl NVTU FWBMVBUF JUT XIPMF TQJOF CFGPSF JU TUBSUT FWBMVBUJOH
WBMVFT JO FBDI DFMM JU BDDVNVMBUFT B QJMF PG VOFWBMVBUFE WBMVFT
BT JU USBWFSTFT UIF TQJOF
$)"15&3  %"5" 4536$563& 03*(".* 

*O NPTU DBTFT XIFO ZPV OFFE B MFǒ GPME ZPV TIPVME VTF
foldl' 5IJT GVODUJPO DBMMFE ƌGPMEMQSJNF ƍ XPSLT UIF TBNF
FYDFQU JU JT TUSJDU *O PUIFS XPSET JU GPSDFT FWBMVBUJPO PG UIF
WBMVFT JOTJEF DPOT DFMMT BT JU USBWFSTFT UIF TQJOF SBUIFS UIBO
BDDVNVMBUJOH VOFWBMVBUFE FYQSFTTJPOT GPS FBDI FMFNFOU PG
UIF MJTU 5IF TUSJDU FWBMVBUJPO IFSF NFBOT JU IBT MFTT OFHBUJWF
FƵFDU PO QFSGPSNBODF PWFS MPOH MJTUT

 )PX UP XSJUF GPME GVODUJPOT


8IFO XF XSJUF GPMET XF CFHJO CZ UIJOLJOH BCPVU XIBU PVS
TUBSU WBMVF GPS UIF GPME JT 5IJT JT VTVBMMZ UIF identity GPS UIF
GVODUJPO 4P XIFO XF TVN UIF FMFNFOUT PG B MJTU UIF JEFOUJUZ
PG TVNNBUJPO JT  8IFO XF NVMUJQMZ UIF FMFNFOUT PG UIF MJTU
UIF JEFOUJUZ JT  5IJT TUBSU WBMVF JT BMTP PVS GBMMCBDL JO DBTF UIF
MJTU JT FNQUZ
/FYU XF DPOTJEFS PVS BSHVNFOUT " GPMEJOH GVODUJPO UBLFT
UXP BSHVNFOUT a BOE b XIFSF a JT HPJOH UP BMXBZT CF POF PG
UIF FMFNFOUT JO UIF MJTU BOE b JT FJUIFS UIF TUBSU WBMVF PS UIF
WBMVF BDDVNVMBUFE BT UIF MJTU JT CFJOH QSPDFTTFE
-FUƊT TBZ XF XBOU UP XSJUF B GVODUJPO UP UBLF UIF ƶSTU UISFF
MFUUFST PG FBDI String WBMVF JO B MJTU PG TUSJOHT BOE DPODBUFOBUF
UIBU SFTVMU JOUP B ƶOBM String 5IF UZQF PG UIF SJHIU GPME GPS MJTUT
JT

foldr :: (a -> b -> b) -> b -> [a] -> b


$)"15&3  %"5" 4536$563& 03*(".* 

'JSTU XFƊMM TFU VQ UIF CFHJOOJOHT PG PVS FYQSFTTJPO

foldr (\ a b -> undefined) []


["Pizza", "Apple", "Banana"]

8F VTFE BO FNQUZ MJTU BT UIF TUBSU WBMVF CVU TJODF XF QMBO UP


SFUVSO B String BT PVS SFTVMU XF DPVME CF B MJUUMF NPSF FYQMJDJU
BCPVU PVS JOUFOU UP CVJME B String BOE NBLF B TNBMM TZOUBDUJD
DIBOHF

foldr (\ a b -> undefined) ""


["Pizza", "Apple", "Banana"]

0G DPVSTF CFDBVTF B String JT B MJTU UIFTF BSF BDUVBMMZ UIF


TBNF WBMVF

Prelude> "" == []
True

#VU "" TJHOBMT JOUFOU XJUI SFTQFDU UP UIF UZQFT JOWPMWFE

Prelude> :t ""
"" :: [Char]
Prelude> :t []
[] :: [t]

.PWJOH BMPOH XF OFYU XBOU UP XPSL PO UIF GVODUJPO 8F


BMSFBEZ LOPX IPX UP UBLF UIF ƶSTU UISFF FMFNFOUT GSPN B MJTU
BOE XF DBO SFVTF UIJT GPS String
$)"15&3  %"5" 4536$563& 03*(".* 

foldr (\ a b -> take 3 a) ""


["Pizza", "Apple", "Banana"]

/PX UIJT XJMM BMSFBEZ UZQFDIFDL BOE XPSL CVU JU EPFTOƊU


NBUDI UIF TFNBOUJDT XF BTLFE GPS

Prelude> let pab = ["Pizza", "Apple", "Banana"]


Prelude> foldr (\ a b -> take 3 a) "" pab
"Piz"
Prelude> foldl (\ b a -> take 3 a) "" pab
"Ban"

8FƊSF POMZ HFUUJOH UIF ƶSTU UISFF MFUUFST PG UIF ƶSTU PS UIF
MBTU TUSJOH EFQFOEJOH PO XIFUIFS XF EJE B SJHIU PS MFǒ GPME
/PUF UIF BSHVNFOU OBNJOH PSEFS EVF UP UIF EJƵFSFODF JO UIF
UZQFT PG foldr BOE foldl

foldr :: (a -> b -> b) -> b -> [a] -> b

foldl :: (b -> a -> b) -> b -> [a] -> b

5IF QSPCMFN IFSF JT UIBU SJHIU OPX XFƊSF OPU BDUVBMMZ GPME
JOH UIF MJTU 8FƊSF KVTU NBQQJOH PVS take 3 PWFS UIF MJTU BOE
TFMFDUJOH UIF ƶSTU PS MBTU SFTVMU

Prelude> map (take 3) pab


["Piz","App","Ban"]
$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> head $ map (take 3) pab


"Piz"
Prelude> last $ map (take 3) pab
"Ban"

4P MFU VT NBLF UIJT B QSPQFS GPME BOE BDUVBMMZ BDDVNVMBUF


UIF SFTVMU CZ NBLJOH VTF PG UIF b BSHVNFOU 3FNFNCFS UIF b
JT ZPVS TUBSU WBMVF 5FDIOJDBMMZ XF DPVME KVTU VTF concat PO UIF
SFTVMU PG IBWJOH NBQQFE take 3 PWFS UIF MJTU PS JUT SFWFSTF JG
XF XBOU UP TJNVMBUF foldl


Prelude> concat $ map (take 3) pab


"PizAppBan"
Prelude> concat $ map (take 3) (reverse pab)
"BanAppPiz"

#VU XF OFFE BO FYDVTF UP QMBZ XJUI foldr BOE foldl TP XFƊMM


QSFUFOE OPOF PG UIJT IBQQFOFE

Prelude> foldr (\ a b -> take 3 a ++ b) "" pab


"PizAppBan"
Prelude> foldl (\ b a -> take 3 a ++ b) "" pab
"BanAppPiz"

)FSF XF DPODBUFOBUFE UIF SFTVMU PG IBWJOH UBLFO UISFF FM


FNFOUT GSPN UIF TUSJOH WBMVF JO PVS JOQVU MJTU POUP UIF GSPOU
PG PVS TUSJOH XFƊSF BDDVNVMBUJOH *G XF XBOU UP CF FYQMJDJU XF
DBO BTTFSU UZQFT GPS UIF WBMVFT
$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> :{
*Prelude| let f a b = take 3
*Prelude| (a :: String) ++
*Prelude| (b :: String)
*Prelude| :}
Prelude> foldr f "" pab
"PizAppBan"

*G XF BTTFSU TPNFUIJOH UIBU JTOƊU USVF UIF UZQFDIFDLFS GXBDLT


VT

Prelude> :{
*Prelude| let f a b = take 3 (a :: String)
*Prelude| ++ (b :: [String])
*Prelude| :}

<interactive>:12:42:
Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [String]
Actual type: [Char]
In the second argument of ‘(++)’,
namely ‘(b :: [String])’
In the expression:
take 3 (a :: String) ++ (b :: [String])

5IJT DBO CF VTFGVM GPS DIFDLJOH UIBU ZPVS NFOUBM NPEFM PG


UIF DPEF JT BDDVSBUF
$)"15&3  %"5" 4536$563& 03*(".* 

&YFSDJTFT %BUBCBTF 1SPDFTTJOH


8SJUF UIF GPMMPXJOH GVODUJPOT GPS QSPDFTTJOH UIJT EBUB

import Data.Time

data DatabaseItem = DbString String


| DbNumber Integer
| DbDate UTCTime
deriving (Eq, Ord, Show)

theDatabase :: [DatabaseItem]
theDatabase =
[ DbDate (UTCTime
(fromGregorian 1911 5 1)
(secondsToDiffTime 34123))
, DbNumber 9001
, DbString "Hello, world!"
, DbDate (UTCTime
(fromGregorian 1921 5 1)
(secondsToDiffTime 34123))
]

 8SJUF B GVODUJPO UIBU ƶMUFST GPS DbDate WBMVFT BOE SFUVSOT


B MJTU PG UIF UTCTime WBMVFT JOTJEF UIFN
$)"15&3  %"5" 4536$563& 03*(".* 

filterDbDate :: [DatabaseItem] -> [UTCTime]


filterDbDate = undefined

 8SJUF B GVODUJPO UIBU ƶMUFST GPS DbNumber WBMVFT BOE SFUVSOT


B MJTU PG UIF Integer WBMVFT JOTJEF UIFN

filterDbNumber :: [DatabaseItem] -> [Integer]


filterDbNumber = undefined

 8SJUF B GVODUJPO UIBU HFUT UIF NPTU SFDFOU EBUF

mostRecent :: [DatabaseItem] -> UTCTime


mostRecent = undefined

 8SJUF B GVODUJPO UIBU TVNT BMM PG UIF DbNumber WBMVFT

sumDb :: [DatabaseItem] -> Integer


sumDb = undefined

 8SJUF B GVODUJPO UIBU HFUT UIF BWFSBHF PG UIF DbNumber WBM


VFT

-- You'll probably need to use fromIntegral


-- to get from Integer to Double.

avgDb :: [DatabaseItem] -> Double


avgDb = undefined
$)"15&3  %"5" 4536$563& 03*(".* 

 'PMEJOH BOE FWBMVBUJPO


8IBU EJƵFSFOUJBUFT foldr BOE foldl JT BTTPDJBUJWJUZ 5IF SJHIU
BTTPDJBUJWJUZ PG foldr NFBOT UIF GPMEJOH GVODUJPO FWBMVBUFT
GSPN UIF JOOFSNPTU DPOT DFMM UP UIF PVUFSNPTU UIF IFBE
 0O
UIF PUIFS IBOE foldl SFDVSTFT VODPOEJUJPOBMMZ UP UIF FOE PG UIF
MJTU UISPVHI TFMGDBMMT BOE UIFO UIF GPMEJOH GVODUJPO FWBMVBUFT
GSPN UIF PVUFSNPTU DPOT DFMM UP UIF JOOFSNPTU

Prelude> take 3 $ foldr (:) [] ([1, 2, 3] ++ undefined)


[1,2,3]
Prelude> take 3 $ foldl (flip (:)) [] ([1, 2, 3] ++ undefined)
*** Exception: Prelude.undefined

-FUƊT EJWF JOUP PVS const FYBNQMF B MJUUMF NPSF DBSFGVMMZ

foldr const 0 [1..5]

8JUI foldr ZPVƊMM FWBMVBUF const 1 (...) CVU const JHOPSFT


UIF SFTU PG UIF GPME UIBU XPVME IBWF PDDVSSFE GSPN UIF FOE PG
UIF MJTU VQ UP UIF OVNCFS 1 TP UIJT SFUVSOT 1 XJUIPVU IBWJOH
FWBMVBUFE BOZ NPSF PG UIF WBMVFT PS UIF TQJOF 0OF XBZ ZPV
DPVME FYBNJOF UIJT GPS ZPVSTFMG XPVME CF

Prelude> foldr const 0 ([1] ++ undefined)


1
$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> head ([1] ++ undefined)


1
Prelude> tail ([1] ++ undefined)
*** Exception: Prelude.undefined

4JNJMBSMZ GPS foldl

foldl (flip const) 0 [1..5]

)FSF foldl XJMM SFDVSTF UP UIF ƶOBM DPOT DFMM FWBMVBUF (flip
const) (...) 5 JHOPSF UIF SFTU PG UIF GPME UIBU XPVME PDDVS
GSPN UIF CFHJOOJOH VQ UP UIF OVNCFS 5 BOE KVTU SFUVSO 
5IF SFMBUJPOTIJQ CFUXFFO foldr BOE foldl JT TVDI UIBU

foldr f z xs = foldl (flip f) z (reverse xs)

#VU POMZ GPS ƶOJUF MJTUT $POTJEFS

Prelude> foldr const 0 (repeat 0 ++ [1,2,3])


0
Prelude> foldl (flip const) 0 (reverse (repeat 1 ++ [1,2,3]))
^CInterrupted.
-- ^^ bottom.

*G XF ƷJQ PVS GPMEJOH GVODUJPO f BOE SFWFSTF UIF MJTU xs foldr


BOE foldl XJMM SFUVSO UIF TBNF SFTVMU
$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> foldr (:) [] [1..5]


[1,2,3,4,5]
Prelude> foldl (flip (:)) [] [1..5]
[5,4,3,2,1]
Prelude> foldl (flip (:)) [] (reverse [1..5])
[1,2,3,4,5]
Prelude> reverse $ foldl (flip (:)) [] [1..5]
[1,2,3,4,5]

 4VNNBSZ
0LBZ XF QSFTFOUFE B MPU PG NBUFSJBM JO UIJT DIBQUFS :PV NJHIU
CF GFFMJOH B MJUUMF XFBSZ PG GPMET SJHIU OPX 4P XIBUƊT UIF FYFD
VUJWF TVNNBSZ

GPMES

 5IF SFTU PG UIF GPME SFDVSTJWF JOWPDBUJPO PG foldr


JT BO
BSHVNFOU UP UIF GPMEJOH GVODUJPO ZPV QBTTFE UP foldr *U
EPFTOƊU EJSFDUMZ TFMGDBMM BT B UBJMDBMM MJLF foldl :PV DPVME
UIJOL PG JU BT BMUFSOBUJOH CFUXFFO BQQMJDBUJPOT PG foldr BOE
ZPVS GPMEJOH GVODUJPO f 5IF OFYU JOWPDBUJPO PG foldr JT
DPOEJUJPOBM PO f IBWJOH BTLFE GPS NPSF PG UIF SFTVMUT PG
IBWJOH GPMEFE UIF MJTU 5IBU JT

foldr :: (a -> b -> b) -> b -> [a] -> b


-- ^
$)"15&3  %"5" 4536$563& 03*(".* 

5IBU ƉCƊ XFƊSF QPJOUJOH BU JO (a -> b -> b) JT UIF SFTU PG UIF


GPME &WBMVBUJOH UIBU FWBMVBUFT UIF OFYU BQQMJDBUJPO PG
foldr

 "TTPDJBUFT UP UIF SJHIU

 8PSLT XJUI JOƶOJUF MJTUT 8F LOPX UIJT CFDBVTF

Prelude> foldr const 0 [1..]


1

 *T B HPPE EFGBVMU DIPJDF XIFOFWFS ZPV XBOU UP USBOTGPSN


EBUB TUSVDUVSFT CF UIFZ ƶOJUF PS JOƶOJUF

GPMEM

 4FMGDBMMT UBJMDBMM
UISPVHI UIF MJTU POMZ CFHJOOJOH UP
QSPEVDF WBMVFT BǒFS JUƊT SFBDIFE UIF FOE PG UIF MJTU

 "TTPDJBUFT UP UIF MFǒ

 $BOOPU CF VTFE XJUI JOƶOJUF MJTUT 5SZ UIF JOƶOJUF MJTU


FYBNQMF FBSMJFS BOE ZPVS 3&1- XJMM IBOH

 *T OFBSMZ VTFMFTT BOE TIPVME BMNPTU BMXBZT CF SFQMBDFE


XJUI foldl' GPS SFBTPOT XFƊMM FYQMBJO MBUFS XIFO XF UBML
BCPVU XSJUJOH FƸDJFOU )BTLFMM QSPHSBNT
$)"15&3  %"5" 4536$563& 03*(".* 

 4DBOT
4DBOT XIJDI XF IBWF NFOUJPOFE BCPWF XPSL TJNJMBSMZ UP
NBQT BOE BMTP UP GPMET -JLF GPMET UIFZ BDDVNVMBUF WBMVFT
JOTUFBE PG LFFQJOH UIF MJTUƊT JOEJWJEVBM WBMVFT TFQBSBUF -JLF
NBQT UIFZ SFUVSO B MJTU PG SFTVMUT *O UIJT DBTF UIF MJTU PG SFTVMUT
TIPXT UIF JOUFSNFEJBUF TUBHFT PG FWBMVBUJPO UIBU JT UIF WBMVFT
UIBU BDDVNVMBUF BT UIF GVODUJPO JT EPJOH JUT XPSL
4DBOT BSF OPU VTFE BT GSFRVFOUMZ BT GPMET BOE PODF ZPV
VOEFSTUBOE UIF CBTJD NFDIBOJDT PG GPMEJOH UIFSF JTOƊU B XIPMF
MPU OFX UP VOEFSTUBOE 4UJMM JU JT VTFGVM UP LOPX BCPVU UIFN
BOE HFU BO JEFB PG XIZ ZPV NJHIU OFFE UIFN
'JSTU MFUƊT UBLF B MPPL BU UIF UZQFT 8FƊMM EP B EJSFDU DPN
QBSJTPO PG UIF UZQFT PG GPMET BOE TDBOT TP UIF EJƵFSFODF JT
DMFBS

foldr :: (a -> b -> b) -> b -> [a] -> b


scanr :: (a -> b -> b) -> b -> [a] -> [b]

foldl :: (b -> a -> b) -> b -> [a] -> b


scanl :: (b -> a -> b) -> b -> [a] -> [b]

5IF QSJNBSZ EJƵFSFODF JT UIBU UIF ƶOBM SFTVMU JT B MJTU GPMET


DBO SFUVSO B MJTU BT B SFTVMU BT XFMM CVU UIFZ EPOƊU BMXBZT
 5IJT

5IF USVUI JT TDBOT BSF OPU VTFE USFNFOEPVTMZ PǒFO CVU UIFSF BSF UJNFT XIFO
ZPV XBOU UP GPME B GVODUJPO PWFS B MJTU BOE SFUVSO B MJTU PG UIF JOUFSNFEJBUF WBMVFT UIBU
ZPV DBO UIFO VTF BT JOQVU UP TPNF PUIFS GVODUJPO 'PS B QBSUJDVMBSMZ FMFHBOU VTF PG
UIJT QMFBTF TFF $ISJT %POFƊT CMPH QPTU BCPVU IJT TPMVUJPO UP UIF XBUFSGBMM QSPCMFN BU
http://chrisdone.com/posts/twitter-problem-loeb
$)"15&3  %"5" 4536$563& 03*(".* 

NFBOT UIBU UIFZ BSF OPU DBUBNPSQIJTNT BOE JO BO JNQPSUBOU


TFOTF BSFOƊU GPMET BU BMM #VU OP NBUUFS 5IF UZQF TJHOBUVSFT
BSF TJNJMBS BOE UIF SPVUFT PG TQJOF USBWFSTBM BOE FWBMVBUJPO
BSF TJNJMBS 5IJT EPFT NFBO UIBU ZPV DBO VTF TDBOT JO QMBDFT
UIBU ZPV DBOƊU VTF B GPME QSFDJTFMZ CFDBVTF ZPV SFUVSO B MJTU PG
SFTVMUT SBUIFS UIBO SFEVDJOH UIF TQJOF PG UIF MJTU
5IF SFTVMUT UIBU TDBOT QSPEVDF DBO CF SFQSFTFOUFE MJLF UIJT

scanr (+) 0 [1..3]


[1 + (2 + (3 + 0)), 2 + (3 + 0), 3 + 0, 0]
[6, 5, 3, 0]

scanl (+) 0 [1..3]


[0, 0 + 1,0 + 1 + 2, 0 + 1 + 2 + 3]
[0, 1, 3, 6]

scanl (+) 1 [1..3]

-- unfolding the definition of scanl a bunch


= [1, 1 + 1, (1 + 1) + 2, ((1 + 1) + 2) + 3]

-- evaluating additions
= [1, 2, 4, 7]

5IFO UP NBLF UIJT NPSF FYQMJDJU BOE QSPQFSMZ FRVBUJPOBM


XF DBO GPMMPX BMPOH XJUI IPX scanl FYQBOET GPS UIJT FYQSFTTJPO
$)"15&3  %"5" 4536$563& 03*(".* 

KVTU CBTFE PO UIF EFƶOJUJPO 'JSTU XF NVTU TFF IPX scanl


JT EFƶOFE 8FƊSF HPJOH UP TIPX ZPV B WFSTJPO PG JU GSPN B
TMJHIUMZ PMEFS base MJCSBSZ GPS ()$ )BTLFMM 5IF EJƵFSFODFT
EPOƊU DIBOHF BOZUIJOH JNQPSUBOU GPS VT IFSF

scanl :: (a -> b -> a) -> a -> [b] -> [a]


scanl f q ls =
q : (case ls of
[] -> []
x:xs -> scanl f (f q x) xs)

*O UIF 3FDVSTJPO DIBQUFS XF XSPUF B SFDVSTJWF GVODUJPO UIBU


SFUVSOFE UIF OUI 'JCPOBDDJ OVNCFS UP VT :PV DBO VTF B TDBO
GVODUJPO UP SFUVSO B MJTU PG 'JCPOBDDJ OVNCFST 8FƊSF HPJOH
UP EP UIJT JO B TPVSDF ƶMF CFDBVTF UIJT XJMM JO UIJT TUBUF SFUVSO
BO JOƶOJUF MJTU GFFM GSFF UP USZ MPBEJOH JU JOUP ZPVS 3&1- BOE
SVOOJOH JU CVU CF RVJDL XJUI UIF DUSMD


fibs = 1 : scanl (+) 1 fibs

8F TUBSU XJUI B WBMVF PG  BOE DPOT UIBU POUP UIF GSPOU PG UIF
MJTU HFOFSBUFE CZ PVS TDBO 5IF MJTU JUTFMG IBT UP CF SFDVSTJWF
CFDBVTF BT XF TBX QSFWJPVTMZ UIF JEFB PG 'JCPOBDDJ OVNCFST
JT UIBU FBDI POF JT UIF TVN PG UIF QSFWJPVT UXP JO UIF TFRVFODF
TDBOOJOH UIF SFTVMUT PG
PWFS B OPOSFDVSTJWF MJTU PG OVNCFST
XIPTF TUBSU WBMVF JT  XPVME KVTU HJWF VT UIJT
$)"15&3  %"5" 4536$563& 03*(".* 

scanl (+) 1 [1..3]


[1, 1 + 1, (1 + 1) + 2, ((1 + 1) + 2) + 3]
[1,2,4,7]

JOTUFBE PG UIF <    > UIBU XFƊSF MPPLJOH GPS

(FUUJOH UIF ƶCPOBDDJ OVNCFS XF XBOU


#VU XF EPOƊU SFBMMZ XBOU BO JOƶOJUF MJTU PG 'JCPOBDDJ OVNCFST
5IBU JTOƊU WFSZ VTFGVM 8F OFFE B NFUIPE UP FJUIFS POMZ UBLF
TPNF OVNCFS PG FMFNFOUT GSPN UIBU MJTU PS UP ƶOE UIF OUI FMF
NFOU BT XF IBE EPOF CFGPSF 'PSUVOBUFMZ UIBUƊT UIF FBTZ QBSU
8FƊMM VTF UIF ƌCBOH CBOHƍ PQFSBUPS !! UP ƶOE UIF OUI FMFNFOU
5IJT PQFSBUPS JT B XBZ UP JOEFY JOUP B MJTU BOE JOEFYJOH JO
)BTLFMM TUBSUT GSPN [FSP 5IBU JT UIF ƶSTU WBMVF JO ZPVS MJTU JT
JOEFYFE BT [FSP #VU PUIFSXJTF UIF PQFSBUPS JT TUSBJHIUGPSXBSE

(!!) :: [a] -> Int -> a

*U OFFET B MJTU BT JUT ƶSTU BSHVNFOU BO Int BT JUT TFDPOE BSHV


NFOU BOE JU SFUVSOT POF FMFNFOU GSPN UIF MJTU 8IJDI JUFN JU
SFUVSOT JT UIF WBMVF UIBU JT JO UIF OUI TQPU XIFSF O JT PVS Int
8F XJMM NPEJGZ PVS TPVSDF ƶMF

fibs = 1 : scanl (+) 1 fibs


fibsN x = fibs !! x
$)"15&3  %"5" 4536$563& 03*(".* 

0ODF XF MPBE UIF ƶMF JOUP PVS 3&1- XF DBO VTF fibsN UP
SFUVSO UIF OUI FMFNFOU PG PVS TDBO

*Main> fibsN 0
1
*Main> fibsN 2
2
*Main> fibsN 6
13

/PX ZPV DBO NPEJGZ ZPVS TPVSDF DPEF UP VTF UIF take PS
takeWhile GVODUJPOT PS UP ƶMUFS JU JO BOZ XBZ ZPV MJLF 0OF
OPUF ƶMUFSJOH XJUIPVU BMTP UBLJOH XPOƊU XPSL UPP XFMM CFDBVTF
ZPVƊSF TUJMM HFUUJOH BO JOƶOJUF MJTU *UƊT B ƶMUFSFE JOƶOJUF MJTU TVSF
CVU TUJMM JOƶOJUF

4DBOT &YFSDJTFT
 .PEJGZ ZPVS fibs GVODUJPO UP POMZ SFUVSO UIF ƶSTU  'J
CPOBDDJ OVNCFST

 .PEJGZ fibs UP SFUVSO UIF 'JCPOBDDJ OVNCFST UIBU BSF MFTT


UIBO 

 5SZ UP XSJUF UIF factorial GVODUJPO GSPN 3FDVSTJPO BT B


TDBO :PVƊMM XBOU scanl BHBJO BOE ZPVS TUBSU WBMVF XJMM CF
 8BSOJOH UIJT XJMM BMTP HFOFSBUF BO JOƶOJUF MJTU TP ZPV
NBZ XBOU UP QBTT JU UISPVHI B take GVODUJPO PS TJNJMBS
$)"15&3  %"5" 4536$563& 03*(".* 

 $IBQUFS &YFSDJTFT


8BSNVQ BOE SFWJFX
'PS UIF GPMMPXJOH TFU PG FYFSDJTFT ZPV BSF OPU FYQFDUFE UP VTF
GPMET 5IFTF BSF JOUFOEFE UP SFWJFX NBUFSJBM GSPN QSFWJPVT
DIBQUFST 'FFM GSFF UP VTF BOZ TZOUBY PS TUSVDUVSF GSPN QSFWJPVT
DIBQUFST UIBU TFFNT BQQSPQSJBUF

 (JWFO UIF GPMMPXJOH TFUT PG DPOTPOBOUT BOE WPXFMT

stops = "pbtdkg"
vowels = "aeiou"

B
8SJUF B GVODUJPO UIBU UBLFT JOQVUT GSPN stops BOE
vowels BOE NBLFT UVQMFT PG BMM QPTTJCMF TUPQWPXFM
TUPQ DPNCJOBUJPOT 5IFTF XJMM OPU BMM DPSSFTQPOE UP
SFBM XPSET JO &OHMJTI BMUIPVHI UIF TUPQWPXFMTUPQ
QBUUFSO JT DPNNPO FOPVHI UIBU NBOZ PG UIFN XJMM
C
.PEJGZ UIBU GVODUJPO TP UIBU JU POMZ SFUVSOT UIF DPN
CJOBUJPOT UIBU CFHJO XJUI B p
D
/PX TFU VQ MJTUT PG OPVOT BOE WFSCT JOTUFBE PG TUPQT
BOE WPXFMT
BOE NPEJGZ UIF GVODUJPO UP NBLF UVQMFT
SFQSFTFOUJOH QPTTJCMF OPVOWFSCOPVO TFOUFODFT

 8IBU EPFT UIF GPMMPXJOH NZTUFSZ GVODUJPO EP 8IBU JT


JUT UZQF 5SZ UP HFU B HPPE TFOTF PG XIBU JU EPFT CFGPSF
ZPV UFTU JU JO UIF 3&1- UP WFSJGZ JU
$)"15&3  %"5" 4536$563& 03*(".* 

seekritFunc x =
div (sum (map length (words x)))
(length (words x))

 8FƊE SFBMMZ MJLF UIF BOTXFS UP CF NPSF QSFDJTF $BO ZPV


SFXSJUF UIBU VTJOH GSBDUJPOBM EJWJTJPO

3FXSJUJOH GVODUJPOT VTJOH GPMET


*O UIF QSFWJPVT DIBQUFS ZPV XSPUF UIFTF GVODUJPOT VTJOH EJSFDU
SFDVSTJPO PWFS MJTUT 5IF HPBM OPX JT UP SFXSJUF UIFN VTJOH
GPMET 8IFSF QPTTJCMF UP HBJO B EFFQFS VOEFSTUBOEJOH PG
GPMEJOH USZ SFXSJUJOH UIF GPME WFSTJPO TP UIBU JU JT QPJOUGSFF
1PJOUGSFF WFSTJPOT PG UIFTF GVODUJPOT XSJUUFO XJUI B GPME
TIPVME MPPL MJLF

myFunc = foldr f z

4P GPS FYBNQMF XJUI UIF and GVODUJPO


$)"15&3  %"5" 4536$563& 03*(".* 

-- Again, this type will be less reusable than


-- the one in GHC 7.10 and newer. Don't worry.

-- direct recursion, not using (&&)


myAnd :: [Bool] -> Bool
myAnd [] = True
myAnd (x:xs) =
if x == False
then False
else myAnd xs

-- direct recursion, using (&&)


myAnd :: [Bool] -> Bool
myAnd [] = True
myAnd (x:xs) = x && myAnd xs

-- fold, not point-free in the folding function


myAnd :: [Bool] -> Bool
myAnd = foldr
(\a b ->
if a == False
then False
else b) True

-- fold, both myAnd and the folding function are point-free now
myAnd :: [Bool] -> Bool
myAnd = foldr (&&) True
$)"15&3  %"5" 4536$563& 03*(".* 

5IF HPBM IFSF JT UP DPOWFSHF PO UIF ƶOBM WFSTJPO XIFSF


QPTTJCMF :PV EPOƊU OFFE UP XSJUF BMM WBSJBUJPOT GPS FBDI FY
BNQMF CVU UIF NPSF WBSJBUJPOT ZPV XSJUF UIF EFFQFS ZPVS
VOEFSTUBOEJOH PG UIFTF GVODUJPOT XJMM CFDPNF

 myOr SFUVSOT True JG BOZ Bool JO UIF MJTU JT True

myOr :: [Bool] -> Bool


myOr = undefined

 myAny SFUVSOT True JG a -> Bool BQQMJFE UP BOZ PG UIF WBMVFT


JO UIF MJTU SFUVSOT True

myAny :: (a -> Bool) -> [a] -> Bool


myAny = undefined

&YBNQMF GPS WBMJEBUJOH myAny

Prelude> myAny even [1, 3, 5]


False
Prelude> myAny odd [1, 3, 5]
True

 8SJUF UXP WFSTJPOT PG myElem 0OF WFSTJPO TIPVME VTF


GPMEJOH BOE UIF PUIFS TIPVME VTF any

myElem :: Eq a => a -> [a] -> Bool


$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> myElem 1 [1..10]


True
Prelude> myElem 1 [2..10]
False

 *NQMFNFOU NZ3FWFSTF EPOƊU XPSSZ BCPVU USZJOH UP NBLF


JU MB[Z

myReverse :: [a] -> [a]


myReverse = undefined

Prelude> myReverse "blah"


"halb"
Prelude> myReverse [1..5]
[5,4,3,2,1]

 8SJUF myMap JO UFSNT PG foldr *U TIPVME IBWF UIF TBNF


CFIBWJPS BT UIF CVJMUJO map

myMap :: (a -> b) -> [a] -> [b]


myMap = undefined

 8SJUF myFilter JO UFSNT PG foldr *U TIPVME IBWF UIF TBNF


CFIBWJPS BT UIF CVJMUJO filter

myFilter :: (a -> Bool) -> [a] -> [a]


myFilter = undefined
$)"15&3  %"5" 4536$563& 03*(".* 

 squish ƷBUUFOT B MJTU PG MJTUT JOUP B MJTU

squish :: [[a]] -> [a]


squish = undefined

 squishMap NBQT B GVODUJPO PWFS B MJTU BOE DPODBUFOBUFT UIF


SFTVMUT

squishMap :: (a -> [b]) -> [a] -> [b]


squishMap = undefined

Prelude> squishMap (\x -> [1, x, 3]) [2]


[1,2,3]
Prelude> squishMap (\x -> "WO " ++ [x] ++ " OT ") "blah"
"WO b OT WO l OT WO a OT WO h OT "

 squishAgain ƷBUUFOT B MJTU PG MJTUT JOUP B MJTU 5IJT UJNF SFVTF


UIF squishMap GVODUJPO

squishAgain :: [[a]] -> [a]


squishAgain = undefined

 myMaximumBy UBLFT B DPNQBSJTPO GVODUJPO BOE B MJTU BOE


SFUVSOT UIF HSFBUFTU FMFNFOU PG UIF MJTU CBTFE PO UIF MBTU
WBMVF UIBU UIF DPNQBSJTPO SFUVSOFE GT GPS

myMaximumBy :: (a -> a -> Ordering) -> [a] -> a


myMaximumBy = undefined
$)"15&3  %"5" 4536$563& 03*(".* 

Prelude> myMaximumBy (\_ _ -> GT) [1..10]


1
Prelude> myMaximumBy (\_ _ -> LT) [1..10]
10
Prelude> myMaximumBy compare [1..10]
10

 myMinimumBy UBLFT B DPNQBSJTPO GVODUJPO BOE B MJTU BOE


SFUVSOT UIF MFBTU FMFNFOU PG UIF MJTU CBTFE PO UIF MBTU WBMVF
UIBU UIF DPNQBSJTPO SFUVSOFE LT GPS

myMinimumBy :: (a -> a -> Ordering) -> [a] -> a


myMinimumBy = undefined

Prelude> myMinimumBy (\_ _ -> GT) [1..10]


10
Prelude> myMinimumBy (\_ _ -> LT) [1..10]
1
Prelude> myMinimumBy compare [1..10]
1

 %FƶOJUJPOT
 " 'PME JT B IJHIFSPSEFS GVODUJPO XIJDI HJWFO B GVODUJPO
UP BDDVNVMBUF UIF SFTVMUT BOE B SFDVSTJWF EBUB TUSVDUVSF
SFUVSOT UIF CVJMU VQ WBMVF 6TVBMMZ B ƌTUBSU WBMVFƍ GPS UIF
$)"15&3  %"5" 4536$563& 03*(".* 

BDDVNVMBUJPO JT QSPWJEFE BMPOH XJUI B GVODUJPO UIBU DBO


DPNCJOF UIF UZQF PG WBMVFT JO UIF EBUB TUSVDUVSF XJUI UIF
BDDVNVMBUJPO 5IF UFSN GPME JT UZQJDBMMZ VTFE XJUI SFG
FSFODF UP DPMMFDUJPOT PG WBMVFT SFGFSFODFE CZ B SFDVSTJWF
EBUBUZQF 'PS B HFOFSBMJ[BUJPO PG ƌCSFBLJOH EPXO TUSVD
UVSFƍ TFF DBUBNPSQIJTN

 " $BUBNPSQIJTN JT B HFOFSBMJ[BUJPO PG GPMET UP BSCJUSBSZ


EBUBUZQFT 8IFSF B GPME BMMPXT ZPV UP CSFBL EPXO B MJTU
JOUP BO BSCJUSBSZ EBUBUZQF B DBUBNPSQIJTN JT B NFBOT PG
CSFBLJOH EPXO UIF TUSVDUVSF PG BOZ EBUBUZQF 5IF bool
:: a -> a -> Bool -> a GVODUJPO JO Data.Bool JT BO FYBNQMF
PG B TJNQMF DBUBNPSQIJTN GPS B TJNQMF OPODPMMFDUJPO
EBUBUZQF 4JNJMBSMZ maybe :: b -> (a -> b) -> Maybe a ->
b JT UIF DBUBNPSQIJTN GPS Maybe 4FF JG ZPV DBO OPUJDF B
QBUUFSO

data Bool = False | True


bool :: a -> a -> Bool -> a

data Maybe a = Nothing | Just a


maybe :: b -> (a -> b) -> Maybe a -> b

data Either a b = Left a | Right b


either :: (a -> c) -> (b -> c) -> Either a b -> c
$)"15&3  %"5" 4536$563& 03*(".* 

 " UBJM DBMM JT UIF ƶOBM SFTVMU PG B GVODUJPO 4PNF FYBNQMFT


PG UBJM DBMMT JO )BTLFMM GVODUJPOT

f x y z = h (subFunction x y z)
where subFunction x y z = g x y z
-- the ``tail call'' is h (subFunction x y z)
-- or more precisely, h.

 Tail recursion JT B GVODUJPO XIPTF UBJM DBMMT BSF SFDVSTJWF


JOWPDBUJPOT PG JUTFMG 5IJT JT EJTUJOHVJTIFE GSPN GVODUJPOT
UIBU DBMM PUIFS GVODUJPOT JO UIFJS UBJM DBMM

f x y z = h (subFunction x y z)
where subFunction x y z = g x y z

5IF BCPWF JT OPU UBJM SFDVSTJWF DBMMT ԗ OPU JUTFMG

f x y z = h (f (x - 1) y z)

4UJMM OPU UBJM SFDVSTJWF ԕ JT JOWPLFE BHBJO CVU OPU JO UIF


UBJMDBMM PG ԕ JUƊT BO BSHVNFOU UP UIF BDUVBM UBJMDBMM ԗ

f x y z = f (x - 1) y z

5IJT JT UBJM SFDVSTJWF ԕ JT DBMMJOH JUTFMG EJSFDUMZ XJUI OP


JOUFSNFEJBSJFT

foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
$)"15&3  %"5" 4536$563& 03*(".* 

/PU UBJM SFDVSTJWF XF HJWF VQ DPOUSPM UP UIF DPNCJOJOH


GVODUJPO ԕ CFGPSF DPOUJOVJOH UISPVHI UIF MJTU foldrƊT SF
DVSTJWF DBMMT XJMM CPVODF CFUXFFO foldr BOE ԕ

foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs

5BJM SFDVSTJWF GPMEM JOWPLFT JUTFMG SFDVSTJWFMZ 5IF DPN


CJOJOH GVODUJPO JT POMZ BO BSHVNFOU UP UIF SFDVSTJWF GPME

 'PMMPXVQ SFTPVSDFT


 )BTLFMM 8JLJ 'PME
https://wiki.haskell.org/Fold

 3JDIBSE #JSE 4FDUJPOT  BOE  PG *OUSPEVDUJPO UP


'VODUJPOBM 1SPHSBNNJOH VTJOH )BTLFMM 


 "OUPOJ %JMMFS *OUSPEVDUJPO UP )BTLFMM

 (SBIBN )VUUPO " UVUPSJBM PO UIF VOJWFSTBMJUZ BOE FY


QSFTTJWFOFTT PG GPME
http://www.cs.nott.ac.uk/~gmh/fold.pdf
$IBQUFS 

"MHFCSBJD EBUBUZQFT

5IF NPTU EFQSFTTJOH


UIJOH BCPVU MJGF BT B
QSPHSBNNFS * UIJOL JT JG
ZPVƊSF GBDFE XJUI B DIVOL
PG DPEF UIBU FJUIFS
TPNFPOF FMTF XSPUF PS
XPSTF TUJMM ZPV XSPUF
ZPVSTFMG CVU OP MPOHFS
EBSF UP NPEJGZ 5IBUƊT
EFQSFTTJOH

4JNPO 1FZUPO +POFT


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

 "MHFCSBJD EBUBUZQFT


8F IBWF TQFOU B MPU PG UJNF UBMLJOH BCPVU EBUBUZQFT BMSFBEZ TP
ZPV NBZ UIJOL XFƊWF DPWFSFE FWFSZUIJOH UIBU OFFET UP CF TBJE
BCPVU UIPTF 5IJT DIBQUFSƊT QVSQPTF JT VMUJNBUFMZ UP FYQMBJO
IPX UP DPOTUSVDU ZPVS PXO EBUBUZQFT JO )BTLFMM 8SJUJOH ZPVS
PXO EBUBUZQFT DBO IFMQ ZPV MFWFSBHF TPNF PG )BTLFMMƊT NPTU
QPXFSGVM GFBUVSFT ƈ QBUUFSO NBUDIJOH UZQF DIFDLJOH BOE
JOGFSFODF ƈ JO B XBZ UIBU NBLFT ZPVS DPEF NPSF DPODJTF BOE
TBGFS #VU UP VOEFSTUBOE UIBU ƶSTU XF OFFE UP FYQMBJO UIF EJG
GFSFODFT BNPOH EBUBUZQFT NPSF GVMMZ BOE VOEFSTUBOE XIBU JU
NFBOT XIFO XF TBZ EBUBUZQFT BSF BMHFCSBJD
" UZQF DBO CF UIPVHIU PG BT BO FOVNFSBUJPO PG DPOTUSVDUPST
UIBU IBWF [FSP PS NPSF BSHVNFOUT 8F XJMM SFUVSO UP UIJT
EFTDSJQUJPO UISPVHIPVU UIF DIBQUFS FBDI UJNF FNQIBTJ[JOH B
EJƵFSFOU QPSUJPO PG JU
)BTLFMM PƵFST TVN UZQFT QSPEVDU UZQFT QSPEVDU UZQFT XJUI
SFDPSE TZOUBY UZQF BMJBTFT GPS FYBNQMF String JT B UZQF BMJBT
GPS [Char]
BOE B TQFDJBM EBUBUZQF DBMMFE B OFXUZQF UIBU PƵFST
B EJƵFSFOU TFU PG PQUJPOT BOE DPOTUSBJOUT GSPN FJUIFS UZQF
TZOPOZNT PS EBUB EFDMBSBUJPOT 8F XJMM FYQMBJO FBDI PG UIFTF
JO EFUBJM JO UIJT DIBQUFS BOE TIPX ZPV IPX UP FYQMPJU UIFN GPS
NBYJNVN VUJMJUZ BOE UZQF TBGFUZ
5IJT DIBQUFS XJMM

5IJT EFTDSJQUJPO TMJHIUMZ FEJUFE GPS PVS QVSQPTFT XBT QSPQPTFE CZ 0SBI ,JUUSFMM JO
UIF #haskell-beginners *3$ DIBOOFM
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

Ƒ FYQMBJO UIF ƌBMHFCSBƍ PG BMHFCSBJD EBUBUZQFT

Ƒ BOBMZ[F UIF DPOTUSVDUJPO PG EBUB DPOTUSVDUPST

Ƒ TQFMM PVU XIFO BOE IPX UP XSJUF ZPVS PXO EBUBUZQFT

Ƒ DMBSJGZ VTBHF PG UZQF TZOPOZNT BOE newtype

Ƒ JOUSPEVDF LJOET

 %BUB EFDMBSBUJPOT SFWJFX


8F PǒFO XBOU UP DSFBUF DVTUPN EBUBUZQFT GPS TUSVDUVSJOH BOE
EFTDSJCJOH UIF EBUB XF BSF QSPDFTTJOH %PJOH TP DBO IFMQ ZPV
BOBMZ[F ZPVS QSPCMFN CZ BMMPXJOH ZPV UP GPDVT ƶSTU PO IPX
ZPV NPEFM UIF EPNBJO CFGPSF ZPV CFHJO UIJOLJOH BCPVU IPX
ZPV XSJUF DPNQVUBUJPOT UIBU TPMWF ZPVS QSPCMFN *U DBO BMTP
NBLF ZPVS DPEF FBTJFS UP SFBE BOE VTF CFDBVTF JU MBZT UIF
EPNBJO NPEFM PVU DMFBSMZ
*O PSEFS UP XSJUF ZPVS PXO UZQFT UIPVHI ZPV NVTU VOEFS
TUBOE UIF XBZ EBUBUZQFT BSF DPOTUSVDUFE JO NPSF EFUBJM UIBO
XFƊWF DPWFSFE TP GBS -FUƊT CFHJO XJUI B SFWJFX PG UIF JNQPS
UBOU QBSUT PG EBUBUZQFT VTJOH UIF EBUB EFDMBSBUJPOT GPS Bool BOE
MJTUT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

data Bool = False | True


-- [1] [2] [3] [4] [5] [6]

data [] a = [ ] | a : [a]
-- [ 7 ] [8] [9]

 ,FZXPSE data UP TJHOBM UIBU XIBU GPMMPXT JT B EBUB EFDMBSB


UJPO PS B EFDMBSBUJPO PG B EBUBUZQF

 5ZQF DPOTUSVDUPS XJUI OP BSHVNFOUT

 &RVBMT TJHO EJWJEFT UIF UZQF DPOTUSVDUPS GSPN JUT EBUB


DPOTUSVDUPST

 %BUB DPOTUSVDUPS *O UIJT DBTF B EBUB DPOTUSVDUPS UIBU UBLFT


OP BSHVNFOUT BOE TP JT DBMMFE B OVMMBSZ DPOTUSVDUPS 5IJT
JT POF PG UIF QPTTJCMF WBMVFT PG UIJT UZQF UIBU DBO TIPX VQ
JO UFSNMFWFM DPEF

 5IF QJQF EFOPUFT B TVN UZQF XIJDI JOEJDBUFT B MPHJDBM


EJTKVODUJPO DPMMPRVJBMMZ PS
JO XIBU WBMVFT DBO IBWF UIBU
UZQF

 $POTUSVDUPS GPS UIF WBMVF True BOPUIFS OVMMBSZ DPOTUSVD


UPS

 5ZQF DPOTUSVDUPS XJUI BO BSHVNFOU "O FNQUZ MJTU IBT


UP CF BQQMJFE UP BO BSHVNFOU JO PSEFS UP CFDPNF B MJTU
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

PG TPNFUIJOH )FSF UIF BSHVNFOU JT B QPMZNPSQIJD UZQF


WBSJBCMF TP UIF MJTUƊT BSHVNFOU DBO CF PG EJƵFSFOU UZQFT

 %BUB DPOTUSVDUPS GPS UIF FNQUZ MJTU

 %BUB DPOTUSVDUPS UIBU UBLFT UXP BSHVNFOUT BO Ԑ BOE BMTP


B [a]

8IFO XF UBML BCPVU B EBUB EFDMBSBUJPO XF BSF UBMLJOH BCPVU


UIF EFƶOJUJPO PG UIF FOUJSF UZQF *G XF UIJOL PG B UZQF BT ƌBO FOV
NFSBUJPO PG DPOTUSVDUPST UIBU IBWF [FSP PS NPSF BSHVNFOUT ƍ
UIFO Bool JT BO FOVNFSBUJPO PG UXP QPTTJCMF DPOTUSVDUPST FBDI
PG XIJDI UBLFT [FSP BSHVNFOUT XIJMF UIF UZQF DPOTUSVDUPS []
FOVNFSBUFT UXP QPTTJCMF DPOTUSVDUPST BOE POF PG UIFN UBLFT
UXP BSHVNFOUT 5IF QJQF EFOPUFT XIBU XF DBMM B TVN UZQF B
UZQF UIBU IBT NPSF UIBO POF DPOTUSVDUPS JOIBCJUJOH JU
*O BEEJUJPO UP TVN UZQFT )BTLFMM BMTP IBT QSPEVDU UZQFT BOE
XFƊMM UBML NPSF BCPVU UIPTF JO B CJU 5IF EBUB DPOTUSVDUPST JO
QSPEVDU UZQFT IBWF NPSF UIBO POF QBSBNFUFS #VU ƶSTU MFUƊT
UVSO PVS BUUFOUJPO UP UIF NFBOJOH PG UIF XPSE DPOTUSVDUPST

 %BUB BOE UZQF DPOTUSVDUPST


5IFSF BSF UXP LJOET PG DPOTUSVDUPST JO )BTLFMM UZQF DPOTUSVD
UPST BOE EBUB DPOTUSVDUPST 5ZQF DPOTUSVDUPST BSF VTFE POMZ
BU UIF UZQF MFWFM JO UZQF TJHOBUVSFT BOE UZQFDMBTT EFDMBSBUJPOT
BOE JOTUBODFT 5ZQFT BSF TUBUJD BOE SFTPMWF BU DPNQJMF UJNF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

%BUB DPOTUSVDUPST DPOTUSVDU UIF WBMVFT BU UFSN MFWFM WBMVFT


ZPV DBO JOUFSBDU XJUI BU SVOUJNF 8F DBMM UIFN DPOTUSVDUPST
CFDBVTF UIFZ EFƶOF B NFBOT PG DSFBUJOH PS CVJMEJOH B UZQF PS
B WBMVF
"MUIPVHI UIF UFSN DPOTUSVDUPS JT PǒFO VTFE UP EFTDSJCF BMM
UZQF DPOTUSVDUPST BOE EBUB DPOTUSVDUPST XF DBO NBLF B EJT
UJODUJPO CFUXFFO DPOTUBOUT BOE DPOTUSVDUPST 5ZQF BOE EBUB
DPOTUSVDUPST UIBU UBLF OP BSHVNFOUT BSF DPOTUBOUT 5IFZ DBO
POMZ TUPSF B ƶYFE UZQF BOE BNPVOU PG EBUB 4P JO UIF Bool
EBUBUZQF GPS FYBNQMF Bool JT B UZQF DPOTUBOU B DPODSFUF UZQF
UIBU JTOƊU XBJUJOH GPS BOZ BEEJUJPOBM JOGPSNBUJPO JO UIF GPSN PG
BO BSHVNFOU JO PSEFS UP CF GVMMZ SFBMJ[FE BT B UZQF *U FOVNFS
BUFT UXP WBMVFT UIBU BSF BMTP DPOTUBOUT True BOE False CFDBVTF
UIFZ UBLF OP BSHVNFOUT 8IJMF XF DBMM True BOE False ƌEBUB
DPOTUSVDUPSTƍ JO GBDU TJODF UIFZ UBLF OP BSHVNFOUT UIFJS WBMVF
JT BMSFBEZ FTUBCMJTIFE BOE OPU CFJOH DPOTUSVDUFE JO BOZ NFBO
JOHGVM TFOTF
)PXFWFS TPNFUJNFT XF OFFE UIF ƷFYJCJMJUZ PG BMMPXJOH EJG
GFSFOU UZQFT PS BNPVOUT PG EBUB UP CF TUPSFE JO PVS EBUBUZQFT
'PS UIPTF UJNFT UZQF BOE EBUB DPOTUSVDUPST NBZ CF QBSBNF
UFSJ[FE 8IFO B DPOTUSVDUPS UBLFT BO BSHVNFOU UIFO JUƊT MJLF B
GVODUJPO JO BU MFBTU POF TFOTF Ƈ JU NVTU CF BQQMJFE UP CFDPNF B
DPODSFUF UZQF PS WBMVF 5IF GPMMPXJOH EBUBUZQFT BSF QTFVEPOZ
NPVT WFSTJPOT PG SFBM EBUBUZQFT JO )BTLFMM 8FƊWF HJWFO UIFN
QTFVEPOZNT CFDBVTF XF XBOU UP GPDVT PO UIF TZOUBY OPU UIF
TFNBOUJDT GPS OPX
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data Trivial = Trivial'


-- [1] [2]

data UnaryTypeCon a = UnaryValueCon a


-- [3] [4]

 )FSF UIF UZQF DPOTUSVDUPS Trivial JT MJLF B DPOTUBOU WBMVF


CVU BU UIF UZQF MFWFM *U UBLFT OP BSHVNFOUT BOE JT UIVT
OVMMBSZ 5IF )BTLFMM 3FQPSU DBMMT UIFTF UZQF DPOTUBOUT UP
EJTUJOHVJTI UIFN GSPN UZQF DPOTUSVDUPST UIBU UBLF BSHV
NFOUT

 5IF EBUB DPOTUSVDUPS Trivial' JT BMTP MJLF B DPOTUBOU WBMVF


CVU JU FYJTUT JO WBMVF UFSN PS SVOUJNF TQBDF 5IFTF BSF
OPU UISFF EJƵFSFOU UIJOHT CVU UISFF EJƵFSFOU XPSET GPS
UIF TBNF TQBDF UIBU UZQFT TFSWF UP EFTDSJCF

 UnaryTypeCon JT B UZQF DPOTUSVDUPS PG POF BSHVNFOU *UƊT B


DPOTUSVDUPS BXBJUJOH B UZQF DPOTUBOU UP CF BQQMJFE UP CVU
JU IBT OP CFIBWJPS JO UIF TFOTF UIBU XF UIJOL PG GVODUJPOT
BT IBWJOH 4VDI UZQFMFWFM GVODUJPOT FYJTU CVU BSF OPU
DPWFSFE JO UIJT CPPL

 UnaryValueCon JT B EBUB DPOTUSVDUPS PG POF BSHVNFOU BXBJU


JOH B WBMVF UP CF BQQMJFE UP "HBJO JU EPFTOƊU CFIBWF MJLF

*G ZPVƊSF JOUFSFTUFE JO MFBSOJOH BCPVU UIJT UPQJD #SFOU :PSHFZƊT CMPH QPTUT BCPVU UZQF
GBNJMJFT BOE GVODUJPOBM EFQFOEFODJFT BSF B HPPE QMBDF UP TUBSU https://byorgey.wordpress.
com/2010/06/29/typed-type-level-programming-in-haskell-part-i-functional-dependencies/
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

B UFSNMFWFM GVODUJPO JO UIF TFOTF PG QFSGPSNJOH BO PQFS


BUJPO PO EBUB *UƊT NPSF MJLF B CPY UP QVU WBMVFT JOUP #F
DBSFGVM XJUI UIF CPYDPOUBJOFS BOBMPHZ BT JU XJMM CFUSBZ
ZPV MBUFS Ƈ OPU BMM UZQF BSHVNFOUT UP DPOTUSVDUPST IBWF
WBMVFMFWFM XJUOFTTFT 4PNF BSF QIBOUPN 8F XJMM DPWFS
UIJT JO B MBUFS DIBQUFS

&BDI PG UIFTF EBUBUZQFT POMZ FOVNFSBUFT POF EBUB DPOTUSVD


UPS 8IFSFBT Trivial' JT UIF POMZ QPTTJCMF DPODSFUF WBMVF GPS
UZQF Trivial UnaryValueCon DPVME TIPX VQ BT EJƵFSFOU MJUFSBM
WBMVFT BU SVOUJNF EFQFOEJOH PO XIBU UZQF PG a JU JT BQQMJFE UP
5IJOL CBDL UP UIF MJTU EBUBUZQF BU UIF UZQF MFWFM ZPV IBWF a :
[a] XIFSF UIF a JT B WBSJBCMF "U UIF UFSN MFWFM JO ZPVS DPEF
UIBU XJMM CF BQQMJFE UP TPNF UZQF PG WBMVFT BOE CFDPNF GPS
FYBNQMF [Char] PS [Integer] PS MJTU PG XIBUFWFS PUIFS DPODSFUF
UZQF ƈ PCWJPVTMZ UIF TFU PG QPTTJCMF MJTUT JT MBSHF


 5ZQF DPOTUSVDUPST BOE LJOET


-FUƊT MPPL BHBJO BU UIF MJTU EBUBUZQF

data [] a = [] | a : [a]

5IJT NVTU CF BQQMJFE UP B DPODSFUF UZQF CFGPSF ZPV IBWF B


MJTU 8F DBO TFF UIF QBSBMMFM XJUI GVODUJPOT XIFO XF MPPL BU
UIF LJOE TJHOBUVSF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

,JOET BSF UIF UZQFT PG UZQFT PS UZQFT POF MFWFM VQ 8F


SFQSFTFOU LJOET JO )BTLFMM XJUI * 8F LOPX TPNFUIJOH JT B
GVMMZ BQQMJFE DPODSFUF UZQF XIFO JU JT SFQSFTFOUFE BT * 8IFO
JU JT * -> * JU MJLF B GVODUJPO JT TUJMM XBJUJOH UP CF BQQMJFE
$PNQBSF UIF GPMMPXJOH

Prelude> let f = not True


Prelude> :t f
f :: Bool

Prelude> let f x = x > 3


Prelude> :t f
f :: (Ord a, Num a) => a -> Bool

5IF ƶSTU f UBLFT OP BSHVNFOUT BOE JT OPU BXBJUJOH BQQMJ


DBUJPO UP BOZUIJOH JO PSEFS UP QSPEVDF B WBMVF TP JUT UZQF
TJHOBUVSF JT KVTU B DPODSFUF UZQF ƈ OPUF UIF MBDL PG B GVODUJPO
BSSPX #VU UIF TFDPOE f JT BXBJUJOH BQQMJDBUJPO UP BO ԧ TP JUT
UZQF TJHOBUVSF IBT B GVODUJPO BSSPX 0ODF XF BQQMZ JU UP B
WBMVF JU BMTP IBT B DPODSFUF UZQF

Prelude> let f x = x > 3


Prelude> :t f 5
f 5 :: Bool

8F RVFSZ UIF LJOE TJHOBUVSF PG B UZQF DPOTUSVDUPS OPU B


EBUB DPOTUSVDUPS
JO ()$J XJUI B :kind PS :k 8F TFF UIBU LJOE
TJHOBUVSFT HJWF VT TJNJMBS JOGPSNBUJPO BCPVU UZQF DPOTUSVDUPST
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

Prelude> :k Bool
Bool :: *
Prelude> :k [Int]
[Int] :: *
Prelude> :k []
[] :: * -> *

#PUI Bool BOE [Int] BSF GVMMZ BQQMJFE DPODSFUF UZQFT TP UIFJS
LJOE TJHOBUVSFT IBWF OP GVODUJPO BSSPXT 5IBU JT UIFZ BSF OPU
BXBJUJOH BQQMJDBUJPO UP BOZUIJOH JO PSEFS UP CF GVMMZ SFBMJ[FE
5IF LJOE PG [] UIPVHI JT * -> * CFDBVTF JU TUJMM OFFET UP CF
BQQMJFE UP B DPODSFUF UZQF CFGPSF JU JT JUTFMG B DPODSFUF UZQF
5IJT JT XIBU UIF DPOTUSVDUPS PG ƌUZQF DPOTUSVDUPSƍ JT SFGFSSJOH
UP

 %BUB DPOTUSVDUPST BOE WBMVFT


8F NFOUJPOFE KVTU B CJU BHP UIBU UIF )BTLFMM 3FQPSU ESBXT B
EJTUJODUJPO CFUXFFO UZQF DPOTUBOUT BOE UZQF DPOTUSVDUPST 8F
DBO ESBX B TJNJMBS EJTUJODUJPO CFUXFFO EBUB DPOTUSVDUPST BOE
DPOTUBOU WBMVFT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data PugType = PugData


-- [1] [2]

data HuskyType a = HuskyData


-- [3] [4]

data DogueDeBordeaux doge = DogueDeBordeaux doge


-- [5] [6]

 PugType JT UIF UZQF DPOTUSVDUPS CVU JU UBLFT OP BSHVNFOUT


TP XF DBO UIJOL PG JU BT CFJOH B UZQF DPOTUBOU 5IJT JT
IPX UIF )BTLFMM 3FQPSU SFGFST UP TVDI UZQFT 5IJT UZQF
FOVNFSBUFT POF DPOTUSVDUPS

 PugData JT UIF POMZ EBUB DPOTUSVDUPS GPS UIF UZQF PugType


*U BMTP IBQQFOT UP CF B DPOTUBOU WBMVF CFDBVTF JU UBLFT OP
BSHVNFOUT BOE TUBOET POMZ GPS JUTFMG 'PS BOZ GVODUJPO
UIBU SFRVJSFT B WBMVF PG UZQF PugType ZPV LOPX UIBU WBMVF
XJMM CF PugData

 HuskyType JT UIF UZQF DPOTUSVDUPS BOE JU UBLFT B TJOHMF QBSB


NFUSJDBMMZ QPMZNPSQIJD UZQF WBSJBCMF BT BO BSHVNFOU *U
BMTP FOVNFSBUFT POF EBUB DPOTUSVDUPS

 HuskyData JT UIF EBUB DPOTUSVDUPS GPS HuskyType /PUF UIBU


UIF UZQF WBSJBCMF BSHVNFOU a EPFT OPU PDDVS BT BO BSHV
NFOU UP HuskyData PS BOZXIFSF FMTF BǒFS UIF = 5IBU NFBOT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

PVS UZQF BSHVNFOU a JT QIBOUPN PS ƌIBT OP XJUOFTTƍ 8F


XJMM FMBCPSBUF PO UIJT MBUFS )FSF HuskyData JT B DPOTUBOU
WBMVF KVTU MJLF PugData

 DogueDeBordeaux JT B UZQF DPOTUSVDUPS BOE IBT B TJOHMF UZQF


WBSJBCMF BSHVNFOU MJLF HuskyType CVU DBMMFE doge JOTUFBE
PG a 8IZ #FDBVTF UIF OBNFT PG WBSJBCMFT EPOƊU NBUUFS
"U BOZ SBUF UIJT UZQF BMTP FOVNFSBUFT POF DPOTUSVDUPS

 DogueDeBordeaux JT UIF MPOF EBUB DPOTUSVDUPS *U IBT UIF


TBNF OBNF BT UIF UZQF DPOTUSVDUPS CVU UIFZ BSF OPU UIF
TBNF UIJOH 5IF doge UZQF WBSJBCMF JO UIF UZQF DPOTUSVD
UPS PDDVST BMTP JO UIF EBUB DPOTUSVDUPS 3FNFNCFS UIBU
CFDBVTF UIFZ BSF UIF TBNF UZQF WBSJBCMF UIFTF NVTU BHSFF
XJUI FBDI PUIFS doge NVTU FRVBM doge *G ZPVS UZQF JT
DogueDeBordeaux [Person] ZPV NVTU OFDFTTBSJMZ IBWF B MJTU
PG Person WBMVFT DPOUBJOFE JO UIF DogueDeBordeaux WBMVF
#VU CFDBVTF DogueDeBordeaux NVTU CF BQQMJFE CFGPSF JUƊT B
DPODSFUF WBMVF JUT MJUFSBM WBMVF BU SVOUJNF DBO DIBOHF

Prelude> :t DogueDeBordeaux
DogueDeBordeaux :: doge -> DogueDeBordeaux doge

8F DBO RVFSZ UIF UZQF PG UIF WBMVF OPU UIF UZQF DPOTUSVD
UPS CVU UIF EBUB DPOTUSVDUPS Ƈ JU DBO CF DPOGVTJOH XIFO
UIF UZQF DPOTUSVDUPS BOE UIF EBUB DPOTUSVDUPS IBWF UIF
TBNF OBNF CVU JUƊT QSFUUZ DPNNPO UP EP UIBU JO )BTLFMM
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

CFDBVTF UIF DPNQJMFS EPFTOƊU DPOGVTF UZQF OBNFT XJUI


WBMVF OBNFT UIF XBZ XF NPSUBMT EP
 *U UFMMT VT UIBU PODF
doge JT CPVOE UP B DPODSFUF UZQF UIFO UIJT XJMM CF B WBMVF
PG UZQF DogueDeBordeaux doge *U JTOƊU B WBMVF ZFU CVU JUƊT B
EFƶOJUJPO GPS IPX UP DPOTUSVDU B WBMVF PG UIBU UZQF

)FSFƊT IPX UP NBLF B WBMVF PG UIF UZQF PG FBDI

myPug = PugData :: PugType

myHusky :: HuskyType a
myHusky = HuskyData

myOtherHusky :: Num a => HuskyType a


myOtherHusky = HuskyData

myOtherOtherHusky :: HuskyType [[[[[[Int]]]]]]


myOtherOtherHusky = HuskyData
-- no witness to the contrary ^

-- This will work because the value 10 agrees


-- with the type variable being bound to Int
myDoge :: DogueDeBordeaux Int
myDoge = DogueDeBordeaux 10
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- This will not work because 10


-- cannot be reconciled with the
-- type variable being bound to String
badDoge :: DogueDeBordeaux String
badDoge = DogueDeBordeaux 10

(JWFO UIJT XF DBO TFF UIBU DPOTUSVDUPST BSF IPX XF DSFBUF


WBMVFT PG UZQFT BOE SFGFS UP UZQFT JO UZQF TJHOBUVSFT 5IFSFƊT B
QBSBMMFM IFSF CFUXFFO UZQF DPOTUSVDUPST BOE EBUB DPOTUSVDUPST
UIBU TIPVME CF OPUFE 8F DBO JMMVTUSBUF UIJT XJUI B OFX DBOJOF
PSJFOUFE EBUBUZQF

data Doggies a =
Husky a
| Mastiff a
deriving (Eq, Show)

-- type constructor awaiting an argument


Doggies

/PUF UIBU UIF LJOE TJHOBUVSF GPS UIF UZQF DPOTUSVDUPS MPPLT
MJLF B GVODUJPO BOE UIF UZQF TJHOBUVSF GPS FJUIFS PG JUT EBUB
DPOTUSVDUPST MPPLT TJNJMBS

Prelude> :k Doggies
Doggies :: * -> *
-- this needs to be applied to become a
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- concrete type

Prelude> :t Husky
Husky :: a -> Doggies a
-- this needs to be applied to become a
-- concrete value

4P UIF CFIBWJPS PG PVS DPOTUSVDUPST JT TVDI UIBU JG UIFZ


EPOƊU UBLF BOZ BSHVNFOUT UIFZ CFIBWF MJLF UZQF PS WBMVF
MFWFM
DPOTUBOUT *G UIFZ EP UBLF BSHVNFOUT UIFZ BDU MJLF UZQF
PS WBMVFMFWFM
GVODUJPOT UIBU EPOƊU EP BOZUIJOH FYDFQU HFU
BQQMJFE

&YFSDJTFT %PH 5ZQFT

(JWFO UIF EBUBUZQFT EFƶOFE JO UIF BCPWF TFDUJPOT

 *T Doggies B UZQF DPOTUSVDUPS PS B EBUB DPOTUSVDUPS

 8IBU JT UIF LJOE PG Doggies

 8IBU JT UIF LJOE PG Doggies String

 8IBU JT UIF UZQF PG Husky 10

 8IBU JT UIF UZQF PG Husky (10 :: Integer)

 8IBU JT UIF UZQF PG Mastiff "Scooby Doo"

 *T DogueDeBordeaux B UZQF DPOTUSVDUPS PS B EBUB DPOTUSVDUPS


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

 8IBU JT UIF UZQF PG DogueDeBordeaux

 8IBU JT UIF UZQF PG DogueDeBordeaux "doggie!"

 8IBUƊT B UZQF BOE XIBUƊT EBUB


"T XFƊWF TBJE UZQFT BSF TUBUJD BOE SFTPMWF BU DPNQJMF UJNF
5ZQFT BSF LOPXO CFGPSF SVOUJNF XIFUIFS UISPVHI FYQMJDJU
EFDMBSBUJPO PS UZQF JOGFSFODF BOE UIBUƊT XIBU NBLFT UIFN
TUBUJD UZQFT *OGPSNBUJPO BCPVU UZQFT EPFT OPU QFSTJTU UISPVHI
UP SVOUJNF %BUB BSF XIBU XFƊSF XPSLJOH XJUI BU SVOUJNF
)FSF DPNQJMF UJNF JT MJUFSBMMZ XIFO ZPVS QSPHSBN JT HFUUJOH
DPNQJMFE CZ ()$ PS DIFDLFE CFGPSF FYFDVUJPO JO B 3&1-
MJLF ()$J 3VOUJNF JT UIF BDUVBM FYFDVUJPO PG ZPVS QSPHSBN
5ZQFT DJSDVNTDSJCF WBMVFT BOE JO UIBU XBZ UIFZ EFTDSJCF XIJDI
WBMVFT BSF ƷPXJOH UISPVHI XIBU QBSUT PG ZPVS QSPHSBN

type constructors -- compile-time

-------------------- phase separation

data constructors -- runtime

#PUI EBUB DPOTUSVDUPST BOE UZQF DPOTUSVDUPST CFHJO XJUI


DBQJUBM MFUUFST CVU B DPOTUSVDUPS CFGPSF UIF = JO B EBUBUZQF EFƶOJ
UJPO JT B UZQF DPOTUSVDUPS XIJMF DPOTUSVDUPST BǕFS UIF = BSF EBUB
DPOTUSVDUPST %BUB DPOTUSVDUPST BSF VTVBMMZ HFOFSBUFE CZ UIF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

EFDMBSBUJPO 0OF USJDLZ CJU IFSF JT UIBU XIFO EBUB DPOTUSVDUPST


UBLF BSHVNFOUT UIPTF BSHVNFOUT SFGFS UP PUIFS UZQFT #FDBVTF
PG UIJT OPU FWFSZUIJOH SFGFSSFE UP JO B EBUBUZQF EFDMBSBUJPO JT
OFDFTTBSJMZ HFOFSBUFE CZ UIBU EBUBUZQF JUTFMG -FUƊT UBLF B MPPL BU
B TIPSU FYBNQMF XJUI EJƵFSFOU EBUBUZQFT UP EFNPOTUSBUF XIBU
XF NFBO CZ UIJT
8F TUBSU XJUI B EBUBUZQF Price UIBU IBT POF UZQF DPOTUSVD
UPS POF EBUB DPOTUSVDUPS BOE POF UZQF BSHVNFOU JO UIF EBUB
DPOTUSVDUPS

data Price =
-- (a)
Price Integer deriving (Eq, Show)
-- (b) [1]

-- type constructor (a)


-- data constructor (b)
-- type argument [1]

5IF WBMVF Price EPFT OPU EFQFOE TPMFMZ PO UIJT EBUBUZQF


EFƶOJUJPO *U EFQFOET PO UIF UZQF Integer BT XFMM *G GPS TPNF
SFBTPO Integer XBTOƊU JO TDPQF XFƊE CF VOBCMF UP HFOFSBUF
Price WBMVFT
/FYU XFƊMM EFƶOF UXP EBUBUZQFT Manufacturer BOE Airline
UIBU BSF FBDI TVN UZQFT XJUI UISFF EBUB DPOTUSVDUPST &BDI EBUB
DPOTUSVDUPS JO UIFTF JT B QPTTJCMF WBMVF PG UIBU UZQF BOE TJODF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

OPOF PG UIFN UBLF BSHVNFOUT BMM BSF HFOFSBUFE CZ UIFJS EFDMB


SBUJPOT BOE BSF NPSF MJLF DPOTUBOU WBMVFT UIBO DPOTUSVDUPST

data Manufacturer =
-- (c)
Mini
-- (d)
| Mazda
-- (e)
| Tata
-- (f)
deriving (Eq, Show)

-- one type constructor (c)


-- three data constructors (d), (e), and (f)
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data Airline =
-- (g)
PapuAir
-- (h)
| CatapultsR'Us
-- (i)
| TakeYourChancesUnited
-- (j)
deriving (Eq, Show)

-- one type constructor (g).


-- three data constructors, (h), (i), and (j)

/FYU XFƊMM MPPL BU BOPUIFS TVN UZQF CVU UIJT POF IBT EBUB
DPOTUSVDUPST UIBU UBLF BSHVNFOUT 'PS UIF UZQF Vehicle UIF
EBUB DPOTUSVDUPST BSF Car BOE Plane TP B Vehicle JT FJUIFS B Car
WBMVF PS B Plane WBMVF 5IFZ FBDI UBLF UZQFT BT BSHVNFOUT KVTU
BT Price JUTFMG UPPL UIF UZQF Integer BT BO BSHVNFOU
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data Vehicle = Car Manufacturer Price


-- (k) (l) [2] [3]
| Plane Airline
-- (m) [4]
deriving (Eq, Show)

-- type constructor (k)


-- two data constructors (l) and (m).
-- three type arguments [2], [3], and [4]
-- two type arguments to (l) are [2] and [3]
-- type argument to (m) is [4]

*O UIF BCPWF UIF EBUBUZQFT BSF HFOFSBUJOH UIF DPOTUSVDUPST


NBSLFE XJUI B MFUUFS 5IF UZQF BSHVNFOUT NBSLFE XJUI B
OVNCFS FYJTUFE QSJPS UP UIF EFDMBSBUJPOT 5IFJS EFƶOJUJPOT
FYJTU PVUTJEF PG UIJT EFDMBSBUJPO BOE UIFZ NVTU CF JO TDPQF UP
CF VTFE BT QBSU PG UIJT EFDMBSBUJPO
&BDI PG UIF BCPWF EBUBUZQFT IBT B EFSJWJOH DMBVTF 8F IBWF
TFFO UIJT CFGPSF BT JU JT VTVBMMZ USVF UIBU ZPV XJMM XBOU UP EF
SJWF BO JOTUBODF PG Show GPS EBUBUZQFT ZPV XSJUF 5IF JOTUBODF
BMMPXT ZPVS EBUB UP CF QSJOUFE UP UIF TDSFFO BT B TUSJOH %F
SJWJOH Eq JT BMTP DPNNPO BOE BMMPXT ZPV UP EFSJWF FRVBMJUZ
PQFSBUJPOT BVUPNBUJDBMMZ GPS NPTU EBUBUZQFT XIFSF UIBU XPVME
NBLF TFOTF 5IFSF BSF PUIFS UZQFDMBTTFT UIBU BMMPX EFSJWBUJPO
JO UIJT NBOOFS BOE JU PCWJBUFT UIF OFFE GPS NBOVBMMZ XSJUJOH
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

JOTUBODFT GPS FBDI EBUBUZQF BOE UZQFDMBTT SFNJOEFS ZPV TBX


BO FYBNQMF PG UIJT JO UIF 5ZQFDMBTTFT DIBQUFS

"T XFƊWF TFFO EBUB DPOTUSVDUPST DBO UBLF BSHVNFOUT 5IPTF
BSHVNFOUT XJMM CF TQFDJƶD UZQFT CVU OPU TQFDJƶD WBMVFT *O
TUBOEBSE )BTLFMM XF DBOƊU DIPPTF TQFDJƶD WBMVFT PG UZQFT BT
UZQF BSHVNFOUT 8F DBOƊU TBZ GPS FYBNQMF ƌBool XJUIPVU UIF
QPTTJCJMJUZ PG False BT B WBMVFƍ *G ZPV BDDFQU Bool BT B WBMJE UZQF
GPS B GVODUJPO PS BT UIF DPNQPOFOU PG B EBUBUZQF ZPV NVTU
BDDFQU BMM PG Bool

&YFSDJTFT 7FIJDMFT
'PS UIFTF FYFSDJTFT XFƊMM VTF UIF EBUBUZQFT EFƶOFE JO UIF BCPWF
TFDUJPO *U XPVME CF HPPE JG ZPVƊE UZQFE UIFN BMM JOUP B TPVSDF
ƶMF BMSFBEZ CVU JG ZPV IBEOƊU QMFBTF EP TP OPX :PV DBO UIFO
EFƶOF TPNF TBNQMF EBUB PO ZPVS PXO PS VTF UIFTF UP HFU ZPV
TUBSUFE

myCar = Car Mini (Price 14000)


urCar = Car Mazda (Price 20000)
clownCar = Car Tata (Price 7000)
doge = Plane PapuAir

 8IBU JT UIF UZQF PG myCar

 (JWFO UIF GPMMPXJOH EFƶOF UIF GVODUJPOT


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

isCar :: Vehicle -> Bool


isCar = undefined

isPlane :: Vehicle -> Bool


isPlane = undefined

areCars :: [Vehicle] -> [Bool]


areCars = undefined

 /PX XFƊSF HPJOH UP XSJUF B GVODUJPO UP UFMM VT UIF NBOV


GBDUVSFS PG B QJFDF PG EBUB

getManu :: Vehicle -> Manufacturer


getManu = undefined

 (JWFO UIBU XFƊSF SFUVSOJOH UIF Manufacturer XIBU XJMM IBQ


QFO JG ZPV VTF UIJT PO Plane EBUB

 "MM SJHIU -FUƊT TBZ ZPVƊWF EFDJEFE UP BEE UIF TJ[F PG UIF
QMBOF BT BO BSHVNFOU UP UIF Plane DPOTUSVDUPS "EE UIBU
UP ZPVS EBUBUZQFT JO UIF BQQSPQSJBUF QMBDFT BOE DIBOHF
ZPVS EBUB BOE GVODUJPOT BQQSPQSJBUFMZ

 %BUB DPOTUSVDUPS BSJUJFT


/PX UIBU XF IBWF B HPPE VOEFSTUBOEJOH PG UIF BOBUPNZ PG
EBUBUZQFT XF XBOU UP TUBSU EFNPOTUSBUJOH XIZ XF DBMM UIFN ƌBM
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

HFCSBJDƍ 8FƊMM TUBSU CZ MPPLJOH BU TPNFUIJOH DBMMFE BSJUZ "SJUZ


SFGFST UP UIF OVNCFS PG BSHVNFOUT B GVODUJPO PS DPOTUSVDUPS
UBLFT " GVODUJPO UIBU UBLFT OP BSHVNFOUT JT DBMMFE OVMMBSZ
XIFSF OVMMBSZ JT B DPOUSBDUJPO PG ƌOVMMƍ BOE ƌBSZƍ /VMM NFBOT
[FSP UIF ƌBSZƍ TVƸY NFBOT ƌPG PS QFSUBJOJOH UPƍ ƌBSZƍ JT B
DPNNPO TVƸY VTFE XIFO UBMLJOH BCPVU NBUIFNBUJDBM BSJUZ
TVDI BT XJUI OVMMBSZ VOBSZ CJOBSZ BOE UIF MJLF
%BUB DPOTUSVDUPST XIJDI UBLF OP BSHVNFOUT BSF BMTP DBMMFE
OVMMBSZ /VMMBSZ EBUB DPOTUSVDUPST TVDI BT True BOE False BSF
DPOTUBOU WBMVFT BU UIF UFSN MFWFM BOE TJODF UIFZ IBWF OP BSHV
NFOUT UIFZ DBOƊU DPOTUSVDU PS SFQSFTFOU BOZ EBUB PUIFS UIBO
UIFNTFMWFT 5IFZ BSF WBMVFT XIJDI TUBOE GPS UIFNTFMWFT BOE
BDU BT B XJUOFTT PG UIF EBUBUZQF UIFZ XFSF EFDMBSFE JO
8FƊWF TBJE UIBU ƌ" UZQF DBO CF UIPVHIU PG BT BO FOVNFSBUJPO
PG DPOTUSVDUPST UIBU IBWF [FSP PS NPSF BSHVNFOUT ƍ TP JU TUBOET
UP SFBTPO UIBU OPU BMM EBUB DPOTUSVDUPST BSF OVMMBSZ :PV IBWF
TFFO FYBNQMFT PG EBUB DPOTUSVDUPST UIBU UBLF POF PS NPSF
BSHVNFOUT CVU XF IBWFOƊU NBEF UPP NVDI PG JU ZFU
&BSMJFS JO UIJT DIBQUFS XF TBX IPX EBUB DPOTUSVDUPST NBZ
UBLF BSHVNFOUT BOE UIBU NBLFT UIFN NPSF MJLF B GVODUJPO
JO UIBU UIFZ NVTU CF BQQMJFE UP TPNFUIJOH CFGPSF ZPV IBWF
B WBMVF %BUB DPOTUSVDUPST UIBU UBLF POF BSHVNFOU BSF DBMMFE
VOBSZ "T XF XJMM TFF MBUFS JO UIJT DIBQUFS EBUB DPOTUSVDUPST
UIBU UBLF NPSF UIBO POF BSHVNFOU BSF DBMMFE QSPEVDUT
"MM PG UIF GPMMPXJOH BSF WBMJE EBUB EFDMBSBUJPOT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- nullary
data Example0 =
Example0 deriving (Eq, Show)

-- unary
data Example1 =
Example1 Int deriving (Eq, Show)

-- product of Int and String


data Example2 =
Example2 Int String deriving (Eq, Show)

Prelude> Example0
Example0
Prelude> Example1 10
Example1 10
Prelude> Example1 10 == Example1 42
False
Prelude> Example2 10 "FlappityBat" == Example2 1 "NC"
False

0VS Example2 JT BO FYBNQMF PG B QSPEVDU MJLF UVQMFT XIJDI


XFƊWF TFFO CFGPSF 5VQMFT DBO UBLF TFWFSBM BSHVNFOUT ƈ BT
NBOZ BT UIFSF BSF JOIBCJUBOUT PG FBDI UVQMF ƈ BOE BSF DPOTJE
FSFE UIF DBOPOJDBM QSPEVDU UZQF UIFZ BSF BOPOZNPVT QSPEVDUT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

CFDBVTF UIFZ IBWF OP OBNF 8FƊMM UBML NPSF BCPVU QSPEVDU


UZQFT TPPO
6OBSZ POF BSHVNFOU
EBUB DPOTUSVDUPST DPOUBJO B TJOHMF
WBMVF PG XIBUFWFS UZQF UIFJS BSHVNFOU XBT 5IF GPMMPXJOH JT B
EBUB EFDMBSBUJPO UIBU DPOUBJOT UIF EBUB DPOTUSVDUPS MyVal MyVal
UBLFT POF Int BSHVNFOU BOE DSFBUFT B UZQF OBNFE MyType

data MyType = MyVal Int deriving (Eq, Show)


-- [1] [2] [3] [4] [5]

 5ZQF DPOTUSVDUPS

 %BUB DPOTUSVDUPS MyVal UBLFT POF UZQF BSHVNFOU TP JU JT


DBMMFE B VOBSZ EBUB DPOTUSVDUPS

 5ZQF BSHVNFOU UP UIF EFƶOJUJPO PG UIF EBUB DPOTUSVDUPS


GSPN <>

 %FSJWJOH DMBVTF

 5ZQFDMBTT JOTUBODFT CFJOH EFSJWFE 8FƊSF HFUUJOH FRVBMJUZ


Eq BOE WBMVF TUSJOHJƶDBUJPO Show GPS GSFF

Prelude> data MyType = MyVal Int deriving (Eq, Show)


Prelude> :t MyVal
MyVal :: Int -> MyType
Prelude> MyVal 10
MyVal 10
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

Prelude> MyVal 10 == MyVal 10


True
Prelude> MyVal 10 == MyVal 9
False

#FDBVTF MyVal IBT POF Int BSHVNFOU B WBMVF PG UZQF MyType


NVTU DPOUBJO POF ƈ POMZ POF ƈ Int WBMVF

 8IBU NBLFT UIFTF EBUBUZQFT


BMHFCSBJD
"MHFCSBJD EBUBUZQFT JO )BTLFMM BSF BMHFCSBJD CFDBVTF XF DBO
EFTDSJCF UIF QBUUFSOT PG BSHVNFOU TUSVDUVSFT VTJOH UXP CBTJD
PQFSBUJPOT TVN BOE QSPEVDU 5IF NPTU EJSFDU XBZ UP FYQMBJO
XIZ UIFZƊSF DBMMFE TVN BOE QSPEVDU JT UP EFNPOTUSBUF TVN
BOE QSPEVDU JO UFSNT PG DBSEJOBMJUZ 5IJT DBO CF VOEFSTUPPE JO
UFSNT PG UIF DBSEJOBMJUZ ZPV TFF XJUI ƶOJUF TFUT 5IJT EPFTOƊU
NBQ QFSGFDUMZ BT XF DBO IBWF JOƶOJUF EBUB TUSVDUVSFT JO )BTLFMM
CVU JUƊT B HPPE XBZ UP CFHJO VOEFSTUBOEJOH BOE BQQSFDJBUJOH
IPX EBUBUZQFT XPSL 8IFO JU DPNFT UP QSPHSBNNJOH MBO
HVBHFT XF BSF DPODFSOFE XJUI DPNQVUBCMF GVODUJPOT OPU KVTU
UIPTF XIJDI DBO HFOFSBUF B TFU

5ZQF UIFPSZ XBT EFWFMPQFE BT BO BMUFSOBUJWF NBUIFNBUJDBM GPVOEBUJPO UP TFU UIFPSZ
8F XPOƊU XSJUF GPSNBM QSPPGT CBTFE PO UIJT CVU UIF XBZ XF SFBTPO JOGPSNBMMZ BCPVU UZQFT
BT QSPHSBNNFST EFSJWFT JO QBSU GSPN UIFJS PSJHJOT BT TFUT 'JOJUF TFUT DPOUBJO B OVNCFS PG
VOJRVF PCKFDUT UIBU OVNCFS JT DBMMFE DBSEJOBMJUZ
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

5IF DBSEJOBMJUZ PG B EBUBUZQF JT UIF OVNCFS PG QPTTJCMF


WBMVFT JU EFƶOFT 5IBU OVNCFS DBO CF BT TNBMM BT  PS BT MBSHF
BT JOƶOJUF GPS FYBNQMF OVNFSJD EBUBUZQFT MJTUT
 ,OPXJOH
IPX NBOZ QPTTJCMF WBMVFT JOIBCJU B UZQF DBO IFMQ ZPV SFBTPO
BCPVU ZPVS QSPHSBNT *O UIF GPMMPXJOH TFDUJPOT XFƊMM TIPX
ZPV IPX UP DBMDVMBUF UIF DBSEJOBMJUZ PG B HJWFO EBUBUZQF CBTFE
TPMFMZ PO IPX JU JT EFƶOFE 'SPN UIFSF XF DBO EFUFSNJOF
IPX NBOZ EJƵFSFOU QPTTJCMF JNQMFNFOUBUJPOT UIFSF BSF PG B
GVODUJPO GPS B HJWFO UZQF TJHOBUVSF
#FGPSF XF HFU JOUP UIF TQFDJƶDT PG IPX UP DBMDVMBUF DBSEJ
OBMJUZ JO HFOFSBM XFƊSF HPJOH UP UBLF DVSTPSZ HMBODFT BU TPNF
EBUBUZQFT XJUI FBTZ UP VOEFSTUBOE DBSEJOBMJUJFT Bool BOE Int
8FƊWF MPPLFE FYUFOTJWFMZ BU UIF Bool UZQF BMSFBEZ TP ZPV
BMSFBEZ LOPX JU POMZ IBT UXP JOIBCJUBOUT UIBU BSF CPUI OVMMBSZ
EBUB DPOTUSVDUPST TP Bool POMZ IBT UXP QPTTJCMF WBMVFT 5IF
DBSEJOBMJUZ PG Bool JT UIFSFGPSF  &WFO XJUIPVU VOEFSTUBOEJOH
UIF SVMFT PG DBSEJOBMJUZ PG TVN UZQFT XF DBO TFF XIZ UIJT JT
USVF
"OPUIFS TFU PG EBUBUZQFT XJUI DBSEJOBMJUZ UIBU JT SFBTPOBCMZ
FBTZ UP VOEFSTUBOE BSF UIF Int UZQFT *O QBSU UIJT JT CFDBVTF Int
BOE SFMBUFE UZQFT Int8 Int16 BOE Int32 IBWF DMFBSMZ EFMJOFBUFE
VQQFS BOE MPXFS CPVOET EFƶOFE CZ UIF BNPVOU PG NFNPSZ
UIFZ BSF QFSNJUUFE UP VTF 8FƊMM VTF Int8 IFSF FWFO UIPVHI JU
JTOƊU WFSZ DPNNPO JO )BTLFMM KVTU CFDBVTF JU IBT UIF TNBMMFTU
TFU PG QPTTJCMF JOIBCJUBOUT BOE UIVT UIF BSJUINFUJD JT B CJU FBTJFS
UP EP 7BMJE Int8 WBMVFT BSF XIPMF OVNCFST GSPN -128 UP 127
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

Int8 JT OPU JODMVEFE JO UIF TUBOEBSE Prelude VOMJLF TUBOEBSE


Int TP XF OFFE UP JNQPSU JU UP TFF JU JO UIF 3&1- CVU BǒFS
XF EP UIBU XF DBO VTF maxBound BOE minBound GSPN UIF Bounded
UZQFDMBTT UP WJFX UIF VQQFS BOE MPXFS WBMVFT

Prelude> import Data.Int

Prelude Data.Int> minBound :: Int8


-128
Prelude Data.Int> maxBound :: Int8
127

(JWFO UIBU UIJT SBOHF JODMVEFT UIF WBMVF 0 XF DBO FBTJMZ


ƶHVSF PVU UIF DBSEJOBMJUZ PG Int8 XJUI TPNF RVJDL BEEJUJPO
     4P UIF DBSEJOBMJUZ PG Int8 JT  "OZXIFSF
JO ZPVS DPEF XIFSF ZPVƊE IBWF B WBMVF PG UZQF Int8 UIFSF BSF
 QPTTJCMF SVOUJNF WBMVFT

&YFSDJTFT $BSEJOBMJUZ
8IJMF XF IBWFOƊU FYQMJDJUMZ EFTDSJCFE UIF SVMFT GPS DBMDVMBUJOH
UIF DBSEJOBMJUZ PG EBUBUZQFT ZFU ZPV NJHIU BMSFBEZ IBWF BO JEFB
PG IPX UP EP JU GPS TJNQMF EBUBUZQFT XJUI OVMMBSZ DPOTUSVDUPST
5SZ OPU UP PWFSUIJOL UIFTF FYFSDJTFT ƈ GPMMPX ZPVS JOUVJUJPO
CBTFE PO XIBU ZPV LOPX

 data PugType = PugData


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

 'PS UIJT POF SFDBMM UIBU Bool JT BMTP EFƶOFE XJUI UIF |

data Airline =
PapuAir
| CatapultsR'Us
| TakeYourChancesUnited

 (JWFO XIBU XF LOPX BCPVU Int8 XIBUƊT UIF DBSEJOBMJUZ PG


Int16

 6TF UIF 3&1- BOE maxBound BOE minBound UP FYBNJOF Int


BOE Integer 8IBU DBO ZPV TBZ BCPVU UIF DBSEJOBMJUZ PG
UIPTF UZQFT

 &YUSB DSFEJU JNQSFTT ZPVS GSJFOET


 8IBUƊT UIF DPOOFD
UJPO CFUXFFO UIF  JO Int8 BOE UIBU UZQFƊT DBSEJOBMJUZ PG


4JNQMF EBUBUZQFT XJUI OVMMBSZ EBUB DPOTUSVDUPST


8FƊMM TUBSU PVS FYQMPSBUJPO PG DBSEJOBMJUZ CZ MPPLJOH BU EBUBUZQFT
XJUI OVMMBSZ EBUB DPOTUSVDUPST

data Example = MakeExample deriving Show

Example JT PVS UZQF DPOTUSVDUPS BOE MakeExample JT PVS POMZ


EBUB DPOTUSVDUPS 4JODF MakeExample UBLFT OP UZQF BSHVNFOUT JU
JT B OVMMBSZ DPOTUSVDUPS 8F LOPX UIBU OVMMBSZ EBUB DPOTUSVD
UPST BSF DPOTUBOUT BOE SFQSFTFOU POMZ UIFNTFMWFT BT WBMVFT *U
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

JT B TJOHMF WBMVF XIPTF POMZ DPOUFOU JT JUT OBNF OPU BOZ PUIFS
EBUB /VMMBSZ DPOTUSVDUPST SFQSFTFOU POF WBMVF XIFO SFBTPOJOH
BCPVU UIF DBSEJOBMJUZ PG UIF UZQFT UIFZ JOIBCJU
"MM ZPV DBO TBZ BCPVU MakeExample JT UIBU UIF DPOTUSVDUPS JT
UIF WBMVF MakeExample BOE UIBU JU JOIBCJUT UIF UZQF Example
5IFSF UIF POMZ JOIBCJUBOU JT MakeExample (JWFO UIBU MakeExample
JT B TJOHMF OVMMBSZ WBMVF TP UIF DBSEJOBMJUZ PG UIF UZQF Example JT
 5IJT JT VTFGVM CFDBVTF JU UFMMT VT UIBU BOZ UJNF XF TFF Example
JO UIF UZQF TJHOBUVSF PG B GVODUJPO XF POMZ IBWF UP SFBTPO
BCPVU POF QPTTJCMF WBMVF

&YFSDJTFT 'PS &YBNQMF


 :PV DBO RVFSZ UIF UZQF PG B WBMVF JO ()$J XJUI UIF :type
DPNNBOE BMTP BCCSFWJBUFE :t &YBNQMF

Prelude> :t False
False :: Bool

8IBU JT UIF UZQF PG EBUB DPOTUSVDUPS MakeExample 8IBU


IBQQFOT XIFO ZPV SFRVFTU UIF UZQF PG Example

 8IBU JG ZPV USZ :info PO Example JO ()$J $BO ZPV EFUFS


NJOF XIBU UZQFDMBTT JOTUBODFT BSF EFƶOFE GPS UIF Example
UZQF VTJOH :info JO ()$J
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

 5SZ NBLJOH B OFX EBUBUZQF MJLF Example CVU XJUI B TJOHMF


UZQF BSHVNFOU BEEFE UP MakeExample TVDI BT Int 8IBU IBT
DIBOHFE XIFO ZPV RVFSZ MakeExample XJUI :type JO ()$J

6OBSZ DPOTUSVDUPST
*O UIF MBTU TFDUJPO XF BTLFE ZPV UP BEE B TJOHMF UZQF BSHVNFOU
UP UIF MakeExample EBUB DPOTUSVDUPS *O EPJOH TP ZPV DIBOHFE
JU GSPN B OVMMBSZ DPOTUSVDUPS UP B VOBSZ POF " VOBSZ EBUB DPO
TUSVDUPS UBLFT POF BSHVNFOU *O UIF EFDMBSBUJPO PG UIF EBUBUZQF
UIBU QBSBNFUFS XJMM CF B UZQF OPU B WBMVF /PX JOTUFBE PG ZPVS
EBUB DPOTUSVDUPS CFJOH B DPOTUBOU PS B LOPXO WBMVF UIF WBMVF
XJMM CF DPOTUSVDUFE BU SVOUJNF GSPN UIF BSHVNFOU XF BQQMJFE
JU UP
%BUBUZQFT UIBU POMZ DPOUBJO B VOBSZ DPOTUSVDUPS BMXBZT IBWF
UIF TBNF DBSEJOBMJUZ BT UIF UZQF UIFZ DPOUBJO *O UIF GPMMPXJOH
Goats IBT UIF TBNF OVNCFS PG JOIBCJUBOUT BT Int

data Goats = Goats Int deriving (Eq, Show)

"OZUIJOH UIBU JT B WBMJE Int NVTU BMTP CF B WBMJE BSHVNFOU


UP UIF Goats DPOTUSVDUPS "OZUIJOH UIBU JTOƊU B WBMJE Int BMTP
JTOƊU B WBMJE DPVOU PG Goats
'PS DBSEJOBMJUZ UIJT NFBOT VOBSZ DPOTUSVDUPST BSF UIF JEFO
UJUZ GVODUJPO
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

 OFXUZQF
)BWJOH HJWFO DPOTJEFSBCMF BUUFOUJPO UP VOBSZ EBUB DPOTUSVD
UPST XF XJMM OPX MPPL BU B XBZ UP EFƶOF B UZQF UIBU DBO POMZ
FWFS IBWF B TJOHMF VOBSZ EBUB DPOTUSVDUPS 8F VTF UIF newtype
LFZXPSE UP NBSL UIFTF UZQFT BT UIFZ BSF EJƵFSFOU GSPN UZQF
EFDMBSBUJPOT NBSLFE XJUI UIF data LFZXPSE BT XFMM BT GSPN UZQF
TZOPOZN EFƶOJUJPOT NBSLFE CZ UIF type LFZXPSE -JLF PUIFS
EBUBUZQFT UIBU IBWF B TJOHMF VOBSZ DPOTUSVDUPS UIF DBSEJOBMJUZ
PG B newtype JT UIF TBNF BT UIBU PG UIF UZQF JU DPOUBJOT
" newtype DBOOPU CF B QSPEVDU UZQF TVN UZQF PS DPOUBJO
OVMMBSZ DPOTUSVDUPST CVU JU IBT B GFX BEWBOUBHFT PWFS B WBOJMMB
data EFDMBSBUJPO 0OF JT UIBU JU IBT OP SVOUJNF PWFSIFBE BT
JU SFVTFT UIF SFQSFTFOUBUJPO PG UIF UZQF JU DPOUBJOT *U DBO EP
UIJT CFDBVTF JUƊT OPU BMMPXFE UP CF B SFDPSE QSPEVDU UZQF
PS
UBHHFE VOJPO TVN UZQF
 5IF EJƵFSFODF CFUXFFO newtype BOE
UIF UZQF JU DPOUBJOT JT HPOF CZ UIF UJNF UIF DPNQJMFS HFOFSBUFT
UIF DPEF
5P JMMVTUSBUF MFUƊT TBZ XF IBWF B GVODUJPO GSPN Int -> Bool
GPS DIFDLJOH XIFUIFS XF IBWF UPP NBOZ HPBUT

tooManyGoats :: Int -> Bool


tooManyGoats n = n > 42

8F NJHIU SVO JOUP B QSPCMFN IFSF JG XF IBE EJƵFSFOU MJNJUT


GPS EJƵFSFOU TPSUT PG MJWFTUPDL 8IBU JG XF NJYFE VQ UIF Int
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

WBMVF GSPN $PXT XIFSF XF NFBOU (PBUT 'PSUVOBUFMZ UIFSFƊT


B XBZ UP BEESFTT UIJT XJUI VOBSZ DPOTUSVDUPST

newtype Goats =
Goats Int deriving (Eq, Show)
newtype Cows =
Cows Int deriving (Eq, Show)

-- Now we can rewrite our type to be


-- safer, pattern matching in order
-- to access the Int inside our data
-- constructor Goats.
tooManyGoats :: Goats -> Bool
tooManyGoats (Goats n) = n > 42

/PX XF DBOƊU NJY VQ PVS MJWFTUPDL DPVOUT

*Main> tooManyGoats (Goats 43)


True
*Main> tooManyGoats (Cows 43)

Couldn't match expected type


‘Goats’ with actual type ‘Cows’
In the first argument of
‘tooManyGoats’, namely ‘(Cows 43)’
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

In the expression: tooManyGoats (Cows 43)

6TJOH newtype DBO EFMJWFS PUIFS BEWBOUBHFT SFMBUFE UP UZQF


DMBTT JOTUBODFT 5P TFF UIFTF XF OFFE UP DPNQBSF OFXUZQFT UP
UZQF TZOPOZNT BOE SFHVMBS EBUB EFDMBSBUJPOT 8FƊMM TUBSU XJUI
B TIPSU DPNQBSJTPO UP UZQF TZOPOZNT
" newtype JT TJNJMBS UP B UZQF TZOPOZN JO UIBU UIF SFQSFTFO
UBUJPOT PG UIF OBNFE UZQF BOE UIF UZQF JU DPOUBJOT BSF JEFOUJDBM
BOE BOZ EJTUJODUJPO CFUXFFO UIFN JT HPOF BU DPNQJMF UJNF 4P
B String SFBMMZ JT B [Char] BOE Goats BCPWF JT SFBMMZ BO Int 0O
UIF TVSGBDF GPS UIF IVNBO XSJUFST BOE SFBEFST PG DPEF UIF
EJTUJODUJPO DBO CF IFMQGVM JO USBDLJOH XIFSF EBUB DBNF GSPN
BOE XIBU JUƊT CFJOH VTFE GPS CVU UIF EJƵFSFODF JT JSSFMFWBOU UP
UIF DPNQJMFS
)PXFWFS POF LFZ DPOUSBTU CFUXFFO B newtype BOE B UZQF
BMJBT JT UIBU ZPV DBO EFƶOF UZQFDMBTT JOTUBODFT GPS newtypeT UIBU
EJƵFS GSPN UIF JOTUBODFT GPS UIFJS VOEFSMZJOH UZQF :PV DBOƊU
EP UIBU GPS UZQF TZOPOZNT -FUƊT UBLF B MPPL BU IPX UIBU XPSLT
8FƊMM ƶSTU EFƶOF B UZQFDMBTT DBMMFE TooMany BOE BO JOTUBODF GPS
Int
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

class TooMany a where


tooMany :: a -> Bool

instance TooMany Int where


tooMany n = n > 42

8F DBO VTF UIBU JOTUBODF JO UIF 3&1- CVU POMZ JG XF BTTJHO


UIF UZQF Int UP XIBUFWFS OVNFSJD MJUFSBM XFƊSF QBTTJOH BT BO
BSHVNFOU CFDBVTF OVNFSJD MJUFSBMT BSF QPMZNPSQIJD 5IBU
MPPLT MJLF UIJT

*Main> tooMany (42 :: Int)

5BLF B NPNFOU BOE QMBZ BSPVOE XJUI UIJT ƈ USZ MFBWJOH PƵ


UIF UZQF EFDMBSBUJPO BOE HJWJOH JU EJƵFSFOU BSHVNFOUT
/PX MFUƊT TBZ GPS ZPVS HPBU DPVOUJOH ZPV XBOUFE B TQFDJBM
JOTUBODF PG TooMany UIBU XJMM IBWF EJƵFSFOU CFIBWJPS GSPN UIF
Int JOTUBODF 6OEFS UIF IPPE Goats JT TUJMM Int CVU UIF newtype
EFDMBSBUJPO XJMM BMMPX ZPV UP EFƶOF B DVTUPN JOTUBODF

newtype Goats = Goats Int deriving Show

instance TooMany Goats where


tooMany (Goats n) = n > 43

5SZ MPBEJOH UIJT BOE QBTTJOH EJƵFSFOU BSHVNFOUT UP JU %PFT


JU CFIBWF EJƵFSFOUMZ UIBO UIF Int JOTUBODF BCPWF %P ZPV TUJMM
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

OFFE UP FYQMJDJUMZ BTTJHO B UZQF UP ZPVS OVNFSJD MJUFSBMT 8IBU


JT UIF UZQF PG tooMany
)FSF XF XFSF BCMF UP NBLF UIF Goats OFXUZQF IBWF BO JO
TUBODF PG TooMany XIJDI IBE EJƵFSFOU CFIBWJPS UIBO UIF UZQF
Int XIJDI JU DPOUBJOT 8F DBOƊU EP UIJT JG JUƊT KVTU B UZQF TZO
POZN %POƊU CFMJFWF VT 5SZ JU
0O UIF PUIFS IBOE XIBU BCPVU UIF DBTF XIFSF XF XBOU UP
SFVTF UIF UZQFDMBTT JOTUBODFT PG UIF UZQF PVS OFXUZQF DPOUBJOT
'PS DPNNPO UZQFDMBTTFT CVJMU JOUP ()$ MJLF Eq Ord Enum BOE
Show XF HFU UIJT GBDJMJUZ GPS GSFF BT ZPVƊWF TFFO XJUI UIF deriving
DMBVTFT JO NPTU EBUBUZQFT
'PS VTFSEFƶOFE UZQFDMBTTFT XF DBO VTF B MBOHVBHF QSBHNB
DBMMFE GeneralizedNewtypeDeriving -BOHVBHF QSBHNBT BMTP DBMMFE
FYUFOTJPOT BSF TQFDJBM JOTUSVDUJPOT UP UIF DPNQJMFS 5IFZ UFMM
UIF DPNQJMFS UP QSPDFTT JOQVU JO XBZT CFZPOE XIBU UIF TUBO
EBSE QSPWJEFT GPS *O UIJT DBTF UIJT QSBHNB XJMM UFMM UIF DPN
QJMFS UP BMMPX PVS newtype UP SFMZ PO B UZQFDMBTT JOTUBODF GPS UIF
UZQF JU DPOUBJOT 8F DBO EP UIJT CFDBVTF UIF SFQSFTFOUBUJPOT
PG UIF newtype BOE UIF UZQF JU DPOUBJOT BSF UIF TBNF 4UJMM JU JT
PVUTJEF PG UIF DPNQJMFSƊT TUBOEBSE CFIBWJPS TP XF NVTU HJWF JU
UIF TQFDJBM JOTUSVDUJPO UP BMMPX VT UP EP UIJT
'JSTU MFUƊT UBLF UIF DBTF PG XIBU XF NVTU EP XJUIPVU HFOFS
BMJ[FE OFXUZQF EFSJWJOH
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

class TooMany a where


tooMany :: a -> Bool

instance TooMany Int where


tooMany n = n > 42

newtype Goats = Goats Int deriving (Eq, Show)

-- this will do the same thing as the


-- Int instance, but we still have to
-- define it separately

instance TooMany Goats where


tooMany (Goats n) = tooMany n

:PV DBO UFTU UIJT ZPVSTFMG UP TFF UIBU UIFZƊMM SFUVSO UIF TBNF
BOTXFST
/PX XFƊMM BEE UIF QSBHNB BU UIF UPQ PG PVS TPVSDF ƶMF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

class TooMany a where


tooMany :: a -> Bool

instance TooMany Int where


tooMany n = n > 42

newtype Goats =
Goats Int deriving (Eq, Show, TooMany)

/PX XF EPOƊU IBWF UP EFƶOF BO JOTUBODF PG TooMany GPS Goats


UIBUƊT NFSFMZ JEFOUJDBM UP UIF Int JOTUBODF 8F DBO SFVTF UIF
JOTUBODF UIBU XF BMSFBEZ IBWF
5IJT JT BMTP OJDF GPS UJNFT XIFO XF XBOU FWFSZ UZQFDMBTT
JOTUBODF UP CF UIF TBNF FYDFQU GPS UIF POF XF XBOU UP DIBOHF

&YFSDJTFT -PHJD (PBUT


 3FVTJOH UIF TooMany UZQFDMBTT XSJUF BO JOTUBODF PG UIF
UZQFDMBTT GPS UIF UZQF (Int, String) 5IJT XJMM SFRVJSF
BEEJOH B MBOHVBHF QSBHNB OBNFE 'MFYJCMF*OTUBODFT JG
ZPV EP OPU VTF B OFXUZQF ƈ ()$ XJMM UFMM ZPV XIBU UP EP

https://ghc.haskell.org/trac/haskell-prime/wiki/FlexibleInstances
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

 .BLF BOPUIFS TooMany JOTUBODF GPS (Int, Int) 4VN UIF


WBMVFT UPHFUIFS VOEFS UIF BTTVNQUJPO UIJT JT B DPVOU PG
HPBUT GSPN UXP ƶFMET

 .BLF BOPUIFS TooMany JOTUBODF UIJT UJNF GPS (Num a, TooMany


a) => (a, a) 5IJT DBO NFBO XIBUFWFS ZPV XBOU TVDI BT
TVNNJOH UIF UXP OVNCFST UPHFUIFS

 4VN UZQFT


/PX UIBU XFƊWF MPPLFE BU EBUB DPOTUSVDUPS BSJUJFT XFƊSF SFBEZ
UP EFƶOF UIF BMHFCSB PG BMHFCSBJD EBUBUZQFT 5IF ƶSTU UIBU XFƊMM
MPPL BU JT UIF TVN UZQF 8FƊWF TFFO TVN UZQFT QSFWJPVTMZ TVDI
BT Bool

data Bool = False | True

8FƊWF NFOUJPOFE QSFWJPVTMZ UIBU UIF | SFQSFTFOUT MPHJDBM


EJTKVODUJPO Ƈ UIBU JT ƌPSƍ 5IJT JT UIF TVN JO BMHFCSBJD EBUBUZQFT
5P LOPX UIF DBSEJOBMJUZ PG TVN UZQFT XF BEE UIF DBSEJOBMJUJFT
PG UIFJS EBUB DPOTUSVDUPST True BOE False UBLF OP UZQF BSHV
NFOUT BOE UIVT BSF OVMMBSZ DPOTUSVDUPST FBDI XJUI B WBMVF PG

/PX XF EP TPNF BSJUINFUJD "T XF TBJE FBSMJFS OVMMBSZ
DPOTUSVDUPST BSF 1 BOE TVN UZQFT BSF + PS BEEJUJPO XIFO XF
BSF UBMLJOH BCPVU DBSEJOBMJUZ
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

-- How many values inhabit Bool?


data Bool = False | True

-- okay lets drop the type constructor for now


-- ?? stands in for our cardinality
True | False = ??

-- Given that |, the sum


-- type syntax, is + or addition
True + False == ??

-- and that False and True both == 1


1 + 1 == ??

-- We see that the cardinality of Bool is


1 + 1 == 2

-- List of all possible counts for Bool


[True, False] -- length is 2

'SPN UIJT XF TFF UIBU XIFO XPSLJOH XJUI B Bool WBMVF XF


NVTU SFBTPO BCPVU UXP QPTTJCMF WBMVFT 4VN UZQFT BSF B XBZ
PG FYQSFTTJOH BMUFSOBUF QPTTJCJMJUJFT XJUIJO B TJOHMF EBUBUZQF
4JHOFE CJU IBSEXBSF JOUFHFST JO )BTLFMM BSF EFƶOFE VTJOH
UIF BGPSFNFOUJPOFE Int8 EBUBUZQF XJUI B SBOHF PG WBMVFT GSPN
 UP  *UƊT OPU EFƶOFE UIJT XBZ CVU ZPV DPVME UIJOL PG
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

JU BT B TVN UZQF PG UIF OVNCFST JO UIBU SBOHF MFBEJOH UP UIF


DBSEJOBMJUZ PG  BT XF TBX

&YFSDJTFT 1JUZ UIF #PPM


 (JWFO B EBUBUZQF

data BigSmall =
Big Bool
| Small Bool
deriving (Eq, Show)

8IBU JT UIF DBSEJOBMJUZ PG UIJT EBUBUZQF )JOU 8F BMSFBEZ


LOPX BoolƊT DBSEJOBMJUZ 4IPX ZPVS XPSL BT EFNPOTUSBUFE
FBSMJFS

 (JWFO B EBUBUZQF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

-- needed to have Int8 in scope


import Data.Int

data NumberOrBool =
Numba Int8
| BoolyBool Bool
deriving (Eq, Show)

-- Example use of Numba, parentheses due to


-- syntactic collision between (-) minus and
-- the negate function
let myNumba = Numba (-128)

8IBU JT UIF DBSEJOBMJUZ PG NumberOrBool 8IBU IBQQFOT JG


ZPV USZ UP DSFBUF B Numba XJUI B OVNFSJD MJUFSBM MBSHFS UIBO
 "OE XJUI B OVNFSJD MJUFSBM TNBMMFS UIBO 

*G ZPV DIPPTF (-128) GPS B WBMVF QSFDJTFMZ ZPVƊMM OPUJDF


ZPV HFU B TQVSJPVT XBSOJOH

Prelude> let n = Numba (-128)


Literal 128 is out of the Int8 range -128..127
If you are trying to write a large negative
literal, use NegativeLiterals

/PX TJODF  JT B QFSGFDUMZ WBMJE Int8 WBMVF ZPV DPVME


DIPPTF UP JHOPSF UIJT 8IBU IBQQFOT JT UIBU (-128) EFTVH
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

BST JOUP (negate 128) 5IF DPNQJMFS TFFT UIBU ZPV FYQFDU
UIF UZQF Int8 CVU Int8ƊT NBY CPVOEBSZ JT  4P FWFO
UIPVHI ZPVƊSF OFHBUJOH  JU IBTOƊU EPOF UIBU TUFQ ZFU
BOE JNNFEJBUFMZ XIJOFT BCPVU  CFJOH MBSHFS UIBO 
0OF XBZ UP BWPJE UIF XBSOJOH JT UIF GPMMPXJOH

Prelude> let n = (-128)


Prelude> let x = Numba n

0S ZPV DBO VTF UIF NegativeLiterals FYUFOTJPO BT JU SFDPN


NFOET

Prelude> :set -XNegativeLiterals


Prelude> let n = Numba (-128)

/PUF UIBU UIF OFHBUJWF MJUFSBMT FYUFOTJPO EPFTOƊU QSFWFOU


UIF XBSOJOH JG ZPV VTF negate

 1SPEVDU UZQFT


8IBU EPFT JU NFBO GPS B UZQF UP CF B QSPEVDU " QSPEVDU UZQFƊT
DBSEJOBMJUZ JT UIF QSPEVDU PG UIF DBSEJOBMJUJFT PG JUT JOIBCJUBOUT
"SJUINFUJDBMMZ QSPEVDUT BSF UIF SFTVMU PG NVMUJQMJDBUJPO 8IFSF
B TVN UZQF XBT FYQSFTTJOH PS B QSPEVDU UZQF FYQSFTTFT BOE
'PS UIPTF UIBU IBWF QSPHSBNNFE JO $MJLF MBOHVBHFT CFGPSF
B QSPEVDU JT MJLF B TUSVDU 'PS UIPTF UIBU IBWFOƊU B QSPEVDU JT B
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

XBZ UP DBSSZ NVMUJQMF WBMVFT BSPVOE JO B TJOHMF EBUB DPOTUSVD


UPS "OZ EBUB DPOTUSVDUPS XJUI UXP PS NPSF UZQF BSHVNFOUT JT
B QSPEVDU
8F TBJE QSFWJPVTMZ UIBU UVQMFT BSF BOPOZNPVT QSPEVDUT
5IF EFDMBSBUJPO PG UIF UVQMF UZQF MPPLT MJLF UIJT

( , ) :: a -> b -> (a, b)

5IJT JT B QSPEVDU MJLF B QSPEVDU UZQF JU HJWFT ZPV B XBZ


UP FODBQTVMBUF UXP QJFDFT PG EBUB PG QPTTJCMZ UIPVHI OPU
OFDFTTBSJMZ
EJƵFSFOU UZQFT JO B TJOHMF WBMVF
8FƊMM MPPL OFYU BU B TPNFXIBU TJMMZ TVN UZQF

data QuantumBool = QuantumTrue


| QuantumFalse
| QuantumBoth deriving (Eq, Show)

8IBU JT UIF DBSEJOBMJUZ PG UIJT TVN UZQF


'PS SFBTPOT UIBU XJMM CFDPNF PCWJPVT B DBSEJOBMJUZ PG 
NBLFT JU IBSEFS UP TIPX UIF EJƵFSFODF CFUXFFO TVN BOE QSPE
VDU DBSEJOBMJUZ TP QuantumBool IBT B DBSEJOBMJUZ PG  /PX XFƊSF
HPJOH UP EFƶOF B QSPEVDU UZQF UIBU DPOUBJOT UXP QuantumBool
WBMVFT

data TwoQs =
MkTwoQs QuantumBool QuantumBool
deriving (Eq, Show)
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

5IF EBUBUZQF TwoQs IBT POF EBUB DPOTUSVDUPS MkTwoQs UIBU


UBLFT UXP BSHVNFOUT NBLJOH JU B QSPEVDU PG UIF UXP UZQFT UIBU
JOIBCJU JU &BDI BSHVNFOU JT PG UZQF QuantumBool XIJDI IBT B
DBSEJOBMJUZ PG 
:PV DBO XSJUF UIJT PVU UP IFMQ ZPV WJTVBMJ[F JU JG ZPV MJLF "
MkTwoQs WBMVF DPVME CF

MkTwoQs QuantumTrue QuantumTrue


MkTwoQs QuantumTrue QuantumFalse
MkTwoQs QuantumTrue QuantumBoth
MkTwoQs QuantumFalse QuantumFalse
-- ...... and so on

/PUF UIBU UIFSF JT OP TQFDJBM TZOUBY EFOPUJOH QSPEVDU UZQFT


BT UIFSF XBT XJUI TVNT BOE | MkTwoQs JT B EBUB DPOTUSVDUPS
UBLJOH UXP UZQF BSHVNFOUT XIJDI CPUI IBQQFO UP CF UIF TBNF
UZQF *U JT B QSPEVDU UZQF UIF QSPEVDU PG UXP QuantumBoolT 5IF
OVNCFS PG QPUFOUJBM WBMVFT UIBU DBO NBOJGFTU JO UIJT UZQF JT UIF
DBSEJOBMJUZ PG POF PG JUT UZQF BSHVNFOUT UJNFT UIF DBSEJOBMJUZ
PG UIF PUIFS 4P XIBU JT UIF DBSEJOBMJUZ PG TwoQs
8F DPVME IBWF BMTP XSJUUFO UIF TwoQs UZQF VTJOH B UZQF BMJBT
BOE UIF UVQMF EBUB DPOTUSVDUPS 5ZQF BMJBTFT DSFBUF UZQF DPO
TUSVDUPST OPU EBUB DPOTUSVDUPST

type TwoQs = (QuantumBool, QuantumBool)

5IF DBSEJOBMJUZ PG UIJT XJMM CF UIF TBNF BT JU XBT QSFWJPVTMZ


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

5IF SFBTPO JUƊT JNQPSUBOU UP VOEFSTUBOE DBSEJOBMJUZ JT UIBU


UIF DBSEJOBMJUZ PG B EBUBUZQF SPVHIMZ FRVBUFT UP IPX EJƸDVMU
JU JT UP SFBTPO BCPVU

3FDPSE TZOUBY
3FDPSET JO )BTLFMM BSF QSPEVDU UZQFT XJUI BEEJUJPOBM TZOUBY UP
QSPWJEF DPOWFOJFOU BDDFTTPST UP ƶFMET XJUIJO UIF SFDPSE -FUƊT
CFHJO CZ EFƶOJOJOH B TJNQMF QSPEVDU UZQF

data Person = MkPerson String Int deriving (Eq, Show)

5IBU JT UIF GBNJMJBS QSPEVDU UZQF TUSVDUVSF UIF MkPerson


EBUB DPOTUSVDUPS UBLFT UXP UZQF BSHVNFOUT JO JUT EFƶOJUJPO B
String WBMVF B OBNF
BOE BO Int WBMVF BO BHF
 5IF DBSEJOBMJUZ
PG UIJT JT GSBOLMZ UFSSJGZJOH
"T XFƊWF TFFO JO QSFWJPVT FYBNQMFT XF DBO VOQBDL UIF
DPOUFOUT PG UIJT UZQF VTJOH GVODUJPOT UIBU SFUVSO UIF WBMVF XF
XBOU GSPN PVS MJUUMF CPY PG WBMVFT

-- these are just sample data


jm = MkPerson "julie" 108
ca = MkPerson "chris" 16

namae :: Person -> String


namae (MkPerson s _) = s
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

*G ZPV VTF UIF namae GVODUJPO JO ZPVS 3&1- JU XJMM SFUVSO


KVTU UIF String WBMVF GSPN ZPVS EBUB
/PX MFUƊT TFF IPX XF DPVME EFƶOF B TJNJMBS QSPEVDU UZQF
CVU XJUI SFDPSE TZOUBY

data Person =
Person { name :: String
, age :: Int }
deriving (Eq, Show)

:PV DBO TFF UIF TJNJMBSJUZ UP UIF Person UZQF EFƶOFE BCPWF
CVU EFƶOJOH JU BT B SFDPSE NFBOT UIFSF BSF OPX OBNFE SFDPSE
ƶFME BDDFTTPST 5IFZƊSF KVTU GVODUJPOT UIBU HP GSPN UIF QSPEVDU
UZQF UP B NFNCFS PG QSPEVDU

Prelude> :t name
name :: Person -> String
Prelude> :t age
age :: Person -> Int

:PV DBO VTF UIJT EJSFDUMZ JO ()$J

Prelude> Person "Papu" 5


Person {name = "Papu", age = 5}

Prelude> let papu = Person "Papu" 5


Prelude> age papu
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

5
Prelude> name papu
"Papu"

:PV DBO BMTP EP JU GSPN EBUB UIBU JT JO B ƶMF $IBOHF UIF jm


BOE ca EBUB BCPWF TP UIBU JU JT OPX PG UZQF Person SFMPBE ZPVS
TPVSDF ƶMF BOE USZ VTJOH UIF SFDPSE ƶFME BDDFTTPST JO ()$J UP
RVFSZ UIF WBMVFT

 /PSNBM GPSN


8FƊWF MPPLFE BU UIF BMHFCSB CFIJOE )BTLFMMƊT BMHFCSBJD EBUBUZQFT
BOE FYQMPSFE IPX UIJT JT VTFGVM GPS VOEFSTUBOEJOH UIF DBSEJ
OBMJUZ PG EBUBUZQFT #VU UIF BMHFCSB EPFTOƊU TUPQ UIFSF "MM UIF
FYJTUJOH BMHFCSBJD SVMFT GPS QSPEVDUT BOE TVNT BQQMZ JO UZQF
TZTUFNT BOE UIBU JODMVEFT UIF EJTUSJCVUJWF QSPQFSUZ -FUƊT UBLF
B MPPL BU IPX UIBU XPSLT JO BSJUINFUJD

2 * (3 + 4)
2 * (7)
14

8F DBO SFXSJUF UIJT XJUI UIF NVMUJQMJDBUJPO EJTUSJCVUFE PWFS


UIF BEEJUJPO BOE PCUBJO UIF TBNF SFTVMU

2 * 3 + 2 * 4
(6) + (8)
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

14

5IJT JT LOPXO BT B ƌTVN PG QSPEVDUTƍ *O OPSNBM BSJUINFUJD


UIF FYQSFTTJPO JT JO OPSNBM GPSN XIFO JUƊT CFFO SFEVDFE UP
B ƶOBM SFTVMU )PXFWFS JG ZPV UIJOL PG UIF OVNFSBMT JO UIF
BCPWF FYQSFTTJPOT BT SFQSFTFOUBUJPOT PG TFU DBSEJOBMJUZ UIFO
UIF TVN PG QSPEVDUT FYQSFTTJPO JT JO OPSNBM GPSN BT UIFSF JT
OP DPNQVUBUJPO UP QFSGPSN
5IF EJTUSJCVUJWF QSPQFSUZ DBO CF HFOFSBMJ[FE

a * (b + c) -> (a * b) + (a * c)

"OE UIJT JT USVF PG )BTLFMMƊT UZQFT BT XFMM 1SPEVDU UZQFT


EJTUSJCVUF PWFS TVN UZQFT 5P QMBZ XJUI UIJT XFƊMM ƶSTU EFƶOF
TPNF EBUBUZQFT

data Fiction = Fiction deriving Show


data Nonfiction = Nonfiction deriving Show

data BookType = FictionBook Fiction


| NonfictionBook Nonfiction
deriving Show

8F EFƶOF UXP UZQFT XJUI POMZ TJOHMF OVMMBSZ JOIBCJUBOUT


Fiction BOE Nonfiction 5IF SFBTPOT GPS EPJOH UIBU NBZ OPU
CF JNNFEJBUFMZ DMFBS CVU SFDBMM UIBU XF TBJE ZPV DBOƊU VTF B
UZQF XIJMF POMZ QFSNJUUJOH POF PG JUT JOIBCJUBOUT BT B QPTTJCMF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

WBMVF :PV DBOƊU BTL GPS B WBMVF PG UZQF Bool XIJMF EFDMBSJOH
JO ZPVS UZQFT UIBU JU NVTU BMXBZT CF True ƈ ZPV NVTU BENJU
UIF QPTTJCJMJUZ PG FJUIFS Bool WBMVF 4P EFDMBSJOH UIF Fiction
BOE Nonfiction UZQFT XJMM BMMPX VT UP GBDUPS PVU UIF CPPL UZQFT
CFMPX

5IFO XF IBWF B TVN UZQF BookType XJUI DPOTUSVDUPST UIBU
UBLF UIF Fiction BOE Nonfiction UZQFT BT BSHVNFOUT *UƊT JNQPS
UBOU UP SFNFNCFS UIBU BMUIPVHI UIF UZQF DPOTUSVDUPST BOE EBUB
DPOTUSVDUPST PG Fiction BOE Nonfiction IBWF UIF TBNF OBNF
UIFZ BSF OPU UIF TBNF BOE JU JT UIF UZQF DPOTUSVDUPST UIBU
BSF UIF BSHVNFOUT UP FictionBook BOE NonfictionBook *G ZPVƊE
MJLF UBLF B NPNFOU BOE SFOBNF UIFN UP EFNPOTUSBUF UIJT UP
ZPVSTFMG
4P XF IBWF PVS TVN UZQF /FYU XFƊSF HPJOH UP EFƶOF B UZQF
TZOPOZN DBMMFE AuthorName BOE B QSPEVDU UZQF DBMMFE Author
5IF UZQF TZOPOZN EPFTOƊU SFBMMZ EP BOZUIJOH FYDFQU IFMQ VT
LFFQ USBDL PG XIJDI String XFƊSF VTJOH JO UIF Author UZQF

type AuthorName = String

data Author = Author (AuthorName, BookType)

5IJT JTOƊU B TVN PG QSPEVDUT TP JU JTOƊU OPSNBM GPSN *U


DBO JO TPNF TFOTF CF FWBMVBUFE UP UFBTF BQBSU UIF WBMVFT UIBU
BSF IJEJOH JO UIF TVN UZQF BookType "HBJO XF DBO BQQMZ UIF
EJTUSJCVUJWF QSPQFSUZ BOE SFXSJUF Author JO OPSNBM GPSN
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

type AuthorName = String

-- If you have them in the same file,


-- you'll need to comment out the previous
-- definitions of Fiction and Nonfiction.

data Author =
Fiction AuthorName
| Nonfiction AuthorName
deriving (Eq, Show)

1SPEVDUT EJTUSJCVUF PWFS TVNT +VTU BT XF XPVME EP XJUI


UIF FYQSFTTJPO a * (b + c) XIFSF UIF JOIBCJUBOUT PG UIF TVN
UZQF BookType BSF UIF b BOE c XF CSPLF UIPTF WBMVFT PVU BOE
NBEF B TVN PG QSPEVDUT /PX JUƊT JO OPSNBM GPSN CFDBVTF
OP GVSUIFS FWBMVBUJPO DBO CF EPOF PG UIFTF DPOTUSVDUPST VOUJM
TPNF PQFSBUJPO PS DPNQVUBUJPO JT EPOF VTJOH UIFTF UZQFT
"OPUIFS FYBNQMF PG OPSNBM GPSN DBO CF GPVOE JO UIF Expr
UZQF XIJDI JT WFSZ DPNNPO UP QBQFST BCPVU UZQF TZTUFNT BOE
QSPHSBNNJOH MBOHVBHFT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data Expr =
Number Int
| Add Expr Expr
| Minus Expr
| Mult Expr Expr
| Divide Expr Expr

5IJT JT JO OPSNBM GPSN CFDBVTF JUƊT B TVN UZQF


PG QSPEVDUT
/VNCFS *OU
"EE &YQS &YQS
ƒ
" TUSJDUFS JOUFSQSFUBUJPO PG OPSNBM GPSN PS ƌTVN PG QSPE
VDUTƍ XPVME SFRVJSF SFQSFTFOUJOH QSPEVDUT XJUI UVQMFT BOE
TVNT XJUI Either 5IF QSFWJPVT EBUBUZQF JO UIBU GPSN XPVME
MPPL MJLF UIF GPMMPXJOH

type Number = Int


type Add = (Expr, Expr)
type Minus = Expr
type Mult = (Expr, Expr)
type Divide = (Expr, Expr)

type Expr =
Either Number
(Either Add
(Either Minus
(Either Mult Divide)))
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

5IJT SFQSFTFOUBUJPO ƶOET BQQMJDBUJPOT JO QSPCMFNT XIFSF


POF JT XSJUJOH GVODUJPOT PS GPMET PWFS UIF SFQSFTFOUBUJPOT PG
EBUBUZQFT TVDI BT XJUI HFOFSJDT BOE NFUBQSPHSBNNJOH 4PNF
PG UIFTF NFUIPET IBWF UIFJS BQQMJDBUJPO JO )BTLFMM CVU TIPVME
CF VTFE KVEJDJPVTMZ BOE BSFOƊU BMXBZT FBTZ UP VTF GPS CFHJOOFST
5IF Either UZQF XJMM CF FYQMBJOFE JO EFUBJM JO UIF OFYU DIBQ
UFS

&YFSDJTFT )PX %PFT :PVS (BSEFO (SPX


 (JWFO UIF UZQF

data FlowerType = Gardenia


| Daisy
| Rose
| Lilac
deriving Show

type Gardener = String

data Garden =
Garden Gardener FlowerType
deriving Show

8IBU JT UIF OPSNBM GPSN PG Garden


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

 $POTUSVDUJOH BOE EFDPOTUSVDUJOH


WBMVFT
5IFSF BSF FTTFOUJBMMZ UXP UIJOHT XF DBO EP XJUI B WBMVF 8F DBO
HFOFSBUF PS DPOTUSVDU JU PS XF DBO NBUDI PO JU BOE DPOTVNF
JU 8F UBMLFE BCPWF BCPVU XIZ EBUB BOE UZQF DPOTUSVDUPST BSF
DBMMFE DPOTUSVDUPST BOE UIJT TFDUJPO XJMM FMBCPSBUF PO UIBU BOE
IPX UP DPOTUSVDU WBMVFT PG EJƵFSFOU UZQFT :PV IBWF BMSFBEZ
CFFO EPJOH UIJT JO QSFWJPVT DIBQUFST CVU XF IPQF UIJT TFDUJPO
XJMM MFBE ZPV UP B EFFQFS VOEFSTUBOEJOH
$POTUSVDUJPO BOE EFDPOTUSVDUJPO PG WBMVFT GPSN B EVBMJUZ
%BUB JT JNNVUBCMF JO )BTLFMM TP WBMVFT DBSSZ XJUI UIFN UIF
JOGPSNBUJPO BCPVU IPX UIFZ XFSF DSFBUFE 8F DBO VTF UIBU
JOGPSNBUJPO XIFO XF DPOTVNF PS EFDPOTUSVDU UIF WBMVF
8FƊMM TUBSU CZ EFƶOJOH B DPMMFDUJPO PG EBUBUZQFT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data GuessWhat =
Chickenbutt deriving (Eq, Show)

data Id a =
MkId a deriving (Eq, Show)

data Product a b =
Product a b deriving (Eq, Show)

data Sum a b =
First a
| Second b
deriving (Eq, Show)

data RecordProduct a b =
RecordProduct { pfirst :: a
, psecond :: b }
deriving (Eq, Show)

/PX UIBU XF IBWF EJƵFSFOU TPSUT PG EBUBUZQFT UP XPSL XJUI


XFƊMM NPWF PO UP DPOTUSVDUJOH WBMVFT PG UIPTF UZQFT

4VN BOE 1SPEVDU


)FSF Sum BOE Product BSF XBZT UP SFQSFTFOU BSCJUSBSZ TVNT BOE
QSPEVDUT JO UZQFT *O PSEJOBSZ )BTLFMM DPEF JUƊT VOMJLFMZ ZPVƊE
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

OFFE PS XBOU OFTUBCMF TVNT BOE QSPEVDUT VOMFTT ZPV XFSF


EPJOH TPNFUIJOH GBJSMZ BEWBODFE CVU IFSF XF VTF UIFN BT B
NFBOT PG EFNPOTUSBUJPO
*G ZPV IBWF KVTU UXP WBMVFT JO B QSPEVDU UIFO UIF DPOWFSTJPO
UP VTJOH Product JT TUSBJHIUGPSXBSE OC 5IF Sum BOE Product
EFDMBSBUJPOT GSPN BCPWF XJMM OFFE UP CF JO TDPQF GPS BMM UIF
GPMMPXJOH FYBNQMFT

$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- if the counts could overflow,


-- then the farm can afford the
-- programmer time to convert
-- the system

newtype NumCow =
NumCow Int
deriving (Eq, Show)

newtype NumPig =
NumPig Int
deriving (Eq, Show)

data Farmhouse =
Farmhouse NumCow NumPig
deriving (Eq, Show)

type Farmhouse' = Product NumCow NumPig

Farmhouse BOE Farmhouse' BSF UIF TBNF


'PS BO FYBNQMF XJUI UISFF WBMVFT JO UIF QSPEVDU JOTUFBE PG
UXP XF NVTU CFHJO UP UBLF BEWBOUBHF PG UIF GBDU UIBU Product
UBLFT UXP BSHVNFOUT POF PG XIJDI DBO BMTP CF BOPUIFS Product
PG WBMVFT *O GBDU ZPV DBO OFTU UIFN BT GBS BT ZPV DBO TUPNBDI
PS VOUJM UIF DPNQJMFS DIPLFT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

newtype NumSheep =
NumSheep Int
deriving (Eq, Show)

data BigFarmhouse =
BigFarmhouse NumCow NumPig NumSheep
deriving (Eq, Show)

type BigFarmhouse' =
Product NumCow (Product NumPig NumSheep)

8F DBO QFSGPSN B TJNJMBS USJDL XJUI Sum

type Name = String


type Age = Int
type LovesMud = Bool

4IFFQ DBO QSPEVDF CFUXFFO  BOE  QPVOET  BOE 


LJMPT
PG XPPM QFS ZFBS *DFMBOEJD TIFFQ EPOƊU QSPEVDF BT NVDI
XPPM QFS ZFBS BT PUIFS CSFFET CVU UIF XPPM UIFZ EP QSPEVDF JT
B ƶOFS XPPM

type PoundsOfWool = Int

data CowInfo =
CowInfo Name Age
deriving (Eq, Show)
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data PigInfo =
PigInfo Name Age LovesMud
deriving (Eq, Show)

data SheepInfo =
SheepInfo Name Age PoundsOfWool
deriving (Eq, Show)

data Animal =
Cow CowInfo
| Pig PigInfo
| Sheep SheepInfo
deriving (Eq, Show)

-- Alternately

type Animal' =
Sum CowInfo (Sum PigInfo SheepInfo)

"HBJO JO UIF 3&1- XF VTF First BOE Second UP QBUUFSO NBUDI


PO UIF EBUB DPOTUSVDUPST PG Sum

-- Getting it right
Prelude> let bess = First (CowInfo "Bess" 4) :: Animal'

Prelude> let elmer' = Second (SheepInfo "Elmer" 5 5)


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

Prelude> let elmer = Second elmer' :: Animal'

-- Making a mistake
Prelude> let elmo' = Second (SheepInfo "Elmo" 5 5)
Prelude> let elmo = First elmo' :: Animal'

Couldn't match expected type ‘CowInfo’


with actual type ‘Sum a0 SheepInfo’
In the first argument of ‘First’, namely
‘(Second (SheepInfo "Elmo" 5 5))’
In the expression:
First (Second (SheepInfo "Elmo" 5 5)) :: Animal'

5IF ƶSTU EBUB DPOTUSVDUPS First IBT UIF BSHVNFOU CowInfo


CVU SheepInfo JT OFTUFE XJUIJO UIF Second DPOTUSVDUPS JU JT UIF
4FDPOE PG UIF 4FDPOE
 8F DBO TFF IPX UIFZ EPOƊU NBUDI BOE
UIF NJTUBLFO BUUFNQU OFTUT JO UIF XSPOH EJSFDUJPO

Prelude> :t First (Second (SheepInfo "Baaaaa" 5 5))


First (Second (SheepInfo "Baaaaa" 5 5))
:: Sum (Sum a SheepInfo) b

Prelude> :info Animal'


type Animal' = Sum CowInfo (Sum PigInfo SheepInfo)
-- Defined at code/animalFarm1.hs:61:1
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

"T XF TBJE UIF BDUVBM UZQFT Sum BOE Product UIFNTFMWFT BSFOƊU
VTFE WFSZ PǒFO JO TUBOEBSE )BTLFMM DPEF CVU JU DBO CF VTFGVM UP
EFWFMPQ BO JOUVJUJPO BCPVU UIJT TUSVDUVSF UP TVN BOE QSPEVDU
UZQFT

$POTUSVDUJOH WBMVFT
0VS ƶSTU EBUBUZQF GuessWhat JT USJWJBM FRVJWBMFOU UP UIF () VOJU
UZQF

trivialValue :: GuessWhat
trivialValue = Chickenbutt

5ZQFT MJLF UIJT BSF TPNFUJNFT VTFE UP TJHOBM EJTDSFUF DPO


DFQUT UIBU ZPV EPOƊU XBOU UP ƷBUUFO JOUP UIF VOJU UZQF 8FƊMM
FMBCPSBUF PO IPX UIJT DBO NBLF DPEF FBTJFS UP VOEFSTUBOE PS
CFUUFS BCTUSBDUFE MBUFS 5IFSF JT OPUIJOH TQFDJBM JO UIF TZOUBY
IFSF 8F KVTU EFƶOF trivialValue UP CF UIF OVMMBSZ EBUB DPO
TUSVDUPS Chickenbutt BOE XF IBWF B WBMVF PG UIF UZQF GuessWhat
/FYU XF MPPL BU B VOBSZ UZQF DPOTUSVDUPS UIBU DPOUBJOT POF
VOBSZ EBUB DPOTUSVDUPS

data Id a =
MkId a deriving (Eq, Show)

#FDBVTF Id IBT BO BSHVNFOU XF IBWF UP BQQMZ JU UP TPNF


UIJOH CFGPSF XF DBO DPOTUSVDU B WBMVF PG UIBU UZQF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- note:
-- MkId :: a -> Id a

idInt :: Id Integer
idInt = MkId 10

"T XFƊWF TBJE UISPVHIPVU UIF CPPL POF PG UIF GVODUJPOBM


QBSUT PG GVODUJPOBM QSPHSBNNJOH JT UIBU GVODUJPOT UIFNTFMWFT
BSF NFSFMZ WBMVFT 4P XF DBO BMTP EP UIJT

idIdentity :: Id (a -> a)
idIdentity = MkId $ \x -> x

5IJT JT B MJUUMF PEE 5IF UZQF Id UBLFT BO BSHVNFOU BOE UIF


EBUB DPOTUSVDUPS MkId UBLFT BO BSHVNFOU PG UIF DPSSFTQPOEJOH
QPMZNPSQIJD UZQF 4P JO PSEFS UP IBWF B WBMVF PG UZQF Id
Integer XF OFFE UP BQQMZ a -> Id a UP BO Integer WBMVF 5IJT
CJOET UIF Ԑ UZQF WBSJBCMF UP Integer BOE BQQMJFT BXBZ UIF (-
>) JO UIF UZQF DPOTUSVDUPS HJWJOH VT Id Integer 8F DBO BMTP
DPOTUSVDU B MkId WBMVF UIBU JT BO JEFOUJUZ GVODUJPO CZ CJOEJOH
UIF Ԑ UP B QPMZNPSQIJD GVODUJPO JO CPUI UIF UZQF BOE UIF UFSN
MFWFM
.PWJOH BMPOH XF UVSO PVS BUUFOUJPO UP PVS QSPEVDU UZQF
XJUI UXP BSHVNFOUT 8FƊSF HPJOH UP EFƶOF TPNF UZQF TZO
POZNT ƶSTU UP NBLF UIJT NPSF SFBEBCMF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

type Awesome = Bool


type Name = String

person :: Product Name Awesome


person = Product "Simon" True

5IF UZQF TZOPOZNT Awesome BOE Name IFSF BSF KVTU GPS DMBSJUZ
5IFZ EPOƊU PCMJHBUF VT UP DIBOHF PVS UFSNT 8F DPVME IBWF
VTFE EBUBUZQFT JOTUFBE PG UZQF TZOPOZNT BT XF XJMM JO UIF TVN
UZQF FYBNQMF CFMPX CVU UIJT JT B RVJDL BOE QBJOMFTT XBZ UP
DPOTUSVDU UIF WBMVF UIBU XF OFFE /PUJDF UIBU XFƊSF SFMZJOH PO
UIF Product EBUB DPOTUSVDUPS UIBU XF EFƶOFE BCPWF 5IF Product
EBUB DPOTUSVDUPS JT B GVODUJPO PG UXP BSHVNFOUT UIF Name BOE
Awesome /PUJDF BMTP UIBU 4JNPOT BSF JOWBSJBCMZ BXFTPNF
/PX XFƊMM VTF UIF Sum UZQF EFƶOFE BCPWF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data Sum a b =
First a
| Second b
deriving (Eq, Show)

data Twitter =
Twitter deriving (Eq, Show)

data AskFm =
AskFm deriving (Eq, Show)

socialNetwork :: Sum Twitter AskFm


socialNetwork = First Twitter

)FSF PVS UZQF JT B TVN PG Twitter PS AskFm 8F EPOƊU IBWF


CPUI WBMVFT BU UIF TBNF UJNF XJUIPVU UIF VTF PG B QSPEVDU
CFDBVTF TVNT BSF B NFBOT PG FYQSFTTJOH EJTKVODUJPO PS UIF
BCJMJUZ UP IBWF POF PG TFWFSBM QPTTJCMF WBMVFT 8F IBWF UP VTF
POF PG UIF EBUB DPOTUSVDUPST HFOFSBUFE CZ UIF EFƶOJUJPO PG Sum
JO PSEFS UP JOEJDBUF XIJDI PG UIF QPTTJCJMJUJFT JO UIF EJTKVODUJPO
XF NFBO UP FYQSFTT $POTJEFS UIF DBTF XIFSF XF NJY UIFN
VQ

Prelude> Second Twitter :: Sum Twitter AskFm

Couldn't match expected type ‘AskFm’ with


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

actual type ‘Twitter’

In the first argument of ‘Second’, namely ‘Twitter’


In the expression:
Second Twitter :: Sum Twitter AskFm

Prelude> First AskFm :: Sum Twitter AskFm

Couldn't match expected type ‘Twitter’ with


actual type ‘AskFm’

In the first argument of ‘First’, namely ‘AskFm’


In the expression:
First AskFm :: Sum Twitter AskFm

5IF BQQSPQSJBUF BTTJHONFOU PG UZQFT UP TQFDJƶD DPOTUSVD


UPST JT EFQFOEFOU PO UIF BTTFSUJPOT JO UIF UZQF 5IF UZQF TJHOB
UVSF Sum Twitter AskFm UFMMT ZPV XIJDI HPFT XJUI UIF EBUB DPO
TUSVDUPS First BOE XIJDI HPFT XJUI UIF EBUB DPOTUSVDUPS Second
8F DBO BTTFSU UIBU PSEFSJOH EJSFDUMZ CZ XSJUJOH B EBUBUZQF MJLF
UIJT

data SocialNetwork =
Twitter
| AskFm
deriving (Eq, Show)
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

/PX UIF EBUB DPOTUSVDUPST GPS Twitter BOE AskFm BSF EJSFDU
JOIBCJUBOUT PG UIF TVN UZQF SocialNetwork XIFSF CFGPSF UIFZ
JOIBCJUFE UIF Sum UZQF /PX MFUƊT DPOTJEFS IPX UIJT NJHIU MPPL
XJUI UZQF TZOPOZNT

type Twitter = String


type AskFm = String

twitter :: Sum Twitter AskFm


twitter = First "Twitter"

-- It has no way of knowing


-- we made a mistake because
-- both values are just Strings
askfm :: Sum Twitter AskFm
askfm = First "AskFm"

5IFSFƊT B QSPCMFN XJUI UIF BCPWF FYBNQMF 5IF OBNF PG


askfm JNQMJFT XF NFBOU Second "AskFm" CVU XF NFTTFE VQ #F
DBVTF XF VTFE UZQF TZOPOZNT JOTUFBE PG EFƶOJOH EBUBUZQFT
UIF UZQF TZTUFN EJEOƊU DBUDI UIF NJTUBLF 5SZ UP BWPJE VT
JOH UZQF TZOPOZNT XJUI VOTUSVDUVSFE EBUB MJLF UFYU PS CJ
OBSZ 5ZQF TZOPOZNT BSF CFTU VTFE XIFO ZPV XBOU TPNF
UIJOH MJHIUFS XFJHIU UIBO OFXUZQFT CVU BMTP XBOU ZPVS UZQF
TJHOBUVSFT UP CF NPSF FYQMJDJU
'JOBMMZ XFƊMM DPOTJEFS UIF QSPEVDU UIBU VTFT SFDPSE TZOUBY
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

Prelude> :t RecordProduct
RecordProduct :: a -> b -> RecordProduct a b

Prelude> :t Product
Product :: a -> b -> Product a b

5IF ƶSTU UIJOH UP OPUJDF JT UIBU ZPV DBO DPOTUSVDU WBMVFT PG


QSPEVDUT UIBU VTF SFDPSE TZOUBY JO B NBOOFS JEFOUJDBM UP UIBU
PG OPOSFDPSE QSPEVDUT 3FDPSET BSF KVTU TZOUBY UP DSFBUF ƶFME
SFGFSFODFT 5IFZ EPOƊU EP NVDI IFBWZ MJǒJOH JO )BTLFMM CVU
UIFZ BSF DPOWFOJFOU

myRecord :: RecordProduct Integer Float


myRecord = RecordProduct 42 0.00001

8F DBO UBLF BEWBOUBHF PG UIF ƶFMET UIBU XF EFƶOFE PO PVS


SFDPSE UP DPOTUSVDU WBMVFT JO B TMJHIUMZ EJƵFSFOU TUZMF 5IJT DBO
CF DPOWFOJFOU GPS NBLJOH UIJOHT B MJUUMF NPSF PCWJPVT

myRecord :: RecordProduct Integer Float


myRecord = RecordProduct { pfirst = 42
, psecond = 0.00001 }

5IJT JT B CJU NPSF DPNQFMMJOH XIFO ZPV IBWF EPNBJO


TQFDJƶD OBNFT GPS UIJOHT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data OperatingSystem =
GnuPlusLinux
| OpenBSDPlusNevermindJustBSDStill
| Mac
| Windows
deriving (Eq, Show)

data ProgrammingLanguage =
Haskell
| Agda
| Idris
| PureScript
deriving (Eq, Show)

data Programmer =
Programmer { os :: OperatingSystem
, lang :: ProgrammingLanguage }
deriving (Eq, Show)

5IFO XF DBO DPOTUSVDU B WBMVF GSPN UIF SFDPSE QSPEVDU


Programmer

Prelude> :t Programmer
Programmer :: OperatingSystem
-> ProgrammingLanguage
-> Programmer
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

nineToFive :: Programmer
nineToFive = Programmer { os = Mac
, lang = Haskell }

-- We can reorder stuff when we use record syntax


feelingWizardly :: Programmer
feelingWizardly = Programmer { lang = Agda
, os = GnuPlusLinux }

&YFSDJTF 1SPHSBNNFST

8SJUF B GVODUJPO UIBU HFOFSBUFT BMM QPTTJCMF WBMVFT PG Programmer


6TF UIF QSPWJEFE MJTUT PG JOIBCJUBOUT PG OperatingSystem BOE
ProgrammingLanguage
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

allOperatingSystems :: [OperatingSystem]
allOperatingSystems =
[ GnuPlusLinux
, OpenBSDPlusNevermindJustBSDStill
, Mac
, Windows
]

allLanguages :: [ProgrammingLanguage]
allLanguages = [Haskell, Agda, Idris, PureScript]

allProgrammers :: [Programmer]
allProgrammers = undefined

Programmer JT B QSPEVDU PG UXP UZQFT ZPV DBO EFUFSNJOF IPX


NBOZ JOIBCJUBOUT PG Programmer ZPV IBWF CZ DBMDVMBUJOH

length allOperatingSystems * length allLanguages

5IJT JT UIF FTTFODF PG IPX QSPEVDU UZQFT BOE UIF OVNCFS


PG JOIBCJUBOUT SFMBUF
5IFSF BSF TFWFSBM XBZT ZPV DPVME XSJUF B GVODUJPO UP EP
UIBU BOE TPNF NBZ QSPEVDF B MJTU UIBU IBT EVQMJDBUF WBMVFT
JO JU *G ZPVS SFTVMUJOH MJTU IBT EVQMJDBUF WBMVFT JO JU ZPV DBO
VTF nub GSPN Data.List UP SFNPWF EVQMJDBUF WBMVFT PWFS ZPVS
allProgrammers WBMVF &JUIFS XBZ JG ZPVS SFTVMU NJOVT BOZ
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

EVQMJDBUF WBMVFT
FRVBMT UIF OVNCFS SFUVSOFE CZ NVMUJQMZJOH
UIPTF MFOHUIT UPHFUIFS ZPVƊWF QSPCBCMZ HPU JU ƶHVSFE PVU 5SZ
UP CF DMFWFS BOE NBLF JU XPSL XJUIPVU NBOVBMMZ UZQJOH PVU
UIF WBMVFT

"DDJEFOUBM CPUUPNT GSPN SFDPSET


8FƊSF HPJOH UP SFVTF UIF QSFWJPVT Programmer EBUBUZQF UP TFF
XIBU IBQQFOT JG XF DPOTUSVDU B WBMVF VTJOH SFDPSE TZOUBY CVU
GPSHFU B ƶFME

Prelude> let partialAf = Programmer {os = GnuPlusLinux}

Fields of ‘Programmer’ not initialised: lang


In the expression: Programmer {os = GnuPlusLinux}
In an equation for ‘partialAf’:
partialAf = Programmer {os = GnuPlusLinux}

-- and if we don't heed this warning...

Prelude> partialAf
Programmer {os = GnuPlusLinux, lang =
*** Exception:
Missing field in record construction lang

%P OPU EP UIJT JO ZPVS DPEF &JUIFS EFƶOF UIF XIPMF SFDPSE


BU PODF PS OPU BU BMM *G ZPV UIJOL ZPV OFFE UIJT ZPVS DPEF OFFET
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

UP CF SFGBDUPSFE 1BSUJBM BQQMJDBUJPO PG UIF EBUB DPOTUSVDUPS


TVƸDFT UP IBOEMF UIJT

-- Works the same as if we'd used record syntax.

data ThereYet =
There Integer Float String Bool
deriving (Eq, Show)

-- who needs a "builder pattern"?


nope :: Float -> String -> Bool -> ThereYet
nope = There 10

notYet :: String -> Bool -> ThereYet


notYet = nope 25.5

notQuite :: Bool -> ThereYet


notQuite = notYet "woohoo"

yusssss :: ThereYet
yusssss = notQuite False

-- Not I, said the Haskell user.

/PUJDF UIF XBZ PVS UZQFT QSPHSFTTFE


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

There :: Integer -> Float -> String -> Bool -> ThereYet
nope :: Float -> String -> Bool -> ThereYet
notYet :: String -> Bool -> ThereYet
notQuite :: Bool -> ThereYet
yusssss :: ThereYet

1FSDPMBUF WBMVFT UISPVHI ZPVS QSPHSBNT OPU CPUUPNT

%FDPOTUSVDUJOH WBMVFT
8IFO XF EJTDVTTFE GPMET XF NFOUJPOFE UIF JEFB PG DBUBNPS
QIJTN 8F FYQMBJOFE UIBU DBUBNPSQIJTN XBT BCPVU EFDPOTUSVDU
JOH MJTUT 5IJT JEFB JT HFOFSBMMZ BQQMJDBCMF UP BOZ EBUBUZQF UIBU
IBT WBMVFT /PX UIBU XFƊWF UIPSPVHIMZ FYQMPSFE DPOTUSVDUJOH
WBMVFT UIF UJNF IBT DPNF UP EFTUSPZ XIBU XF IBWF CVJMU 8BJU
OP ƈ XF NFBO EFDPOTUSVDU
8F CFHJO BT BMXBZT XJUI TPNF EBUBUZQFT

" GBWPSJUF TOBDL PG UIF /PSUI "NFSJDBO :FUJ JT CPUUPNQSPQBHBUJOH )BTLFMMFST
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

newtype Name = Name String deriving Show


newtype Acres = Acres Int deriving Show

-- FarmerType is a Sum
data FarmerType = DairyFarmer
| WheatFarmer
| SoybeanFarmer deriving Show

-- Farmer is a plain ole product of


-- Name, Acres, and FarmerType
data Farmer =
Farmer Name Acres FarmerType deriving Show

/PX XFƊSF HPJOH UP XSJUF B WFSZ CBTJD GVODUJPO UIBU CSFBLT


EPXO BOE VOQBDLT UIF EBUB JOTJEF PVS DPOTUSVDUPST

isDairyFarmer :: Farmer -> Bool


isDairyFarmer (Farmer _ _ DairyFarmer) = True
isDairyFarmer _ = False

DairyFarmer JT POF WBMVF PG UIF FarmerType UZQF UIBU JT QBDLFE


VQ JOTJEF PVS Farmer QSPEVDU UZQF #VU PVS GVODUJPO DBO QVMM
UIBU WBMVF PVU QBUUFSO NBUDI PO JU BOE UFMM VT KVTU XIBU XFƊSF
MPPLJOH GPS
/PX BO BMUFSOBUF GPSNVMBUJPO XJUI B QSPEVDU UIBU VTFT
SFDPSE TZOUBY
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data FarmerRec =
FarmerRec { name :: Name
, acres :: Acres
, farmerType :: FarmerType } deriving Show

isDairyFarmerRec :: FarmerRec -> Bool


isDairyFarmerRec farmer = case farmerType farmer of
DairyFarmer -> True
_ -> False

5IJT JT KVTU BOPUIFS XBZ PG VOQBDLJOH PS EFDPOTUSVDUJOH UIF


DPOUFOUT PG B QSPEVDU UZQF

"DDJEFOUBM CPUUPNT GSPN SFDPSET


8F UBLF CPUUPNT WFSZ TFSJPVTMZ :PV DBO FBTJMZ QSPQBHBUF CPUUPNT
UISPVHI SFDPSE UZQFT BOE XF JNQMPSF ZPV OPU UP EP TP 1MFBTF
EP OPU EP UIJT

data Automobile = Null


| Car { make :: String
, model :: String
, year :: Integer }
deriving (Eq, Show)

5IJT JT B UFSSJCMF UIJOH UP EP GPS B DPVQMF PG SFBTPOT 0OF


JT UIJT Null OPOTFOTF )BTLFMM PƵFST ZPV UIF QFSGFDUMZ MPWFMZ
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

EBUBUZQF Maybe XIJDI ZPV TIPVME VTF JOTUFBE 4FDPOEMZ DPO


TJEFS UIF DBTF XIFSF POF IBT B Null WBMVF CVU ZPVƊWF VTFE POF
PG UIF SFDPSE BDDFTTPST

Prelude> make Null


"*** Exception: No match in record selector make

-- Don't.

)PX EP XF ƶY UIJT 8FMM ƶSTU XIFOFWFS XF IBWF B QSPEVDU


UIBU VTFT SFDPSE BDDFTTPST LFFQ JU TFQBSBUF PG BOZ TVN UZQF
UIBU JT XSBQQJOH JU 5P EP UIJT TQMJU PVU UIF QSPEVDU JOUP BO
JOEFQFOEFOU UZQF XJUI JUT PXO UZQF DPOTUSVDUPS JOTUFBE PG
POMZ BT BO JOMJOF EBUB DPOTUSVDUPS QSPEVDU

-- Split out the record/product

data Car = Car { make :: String


, model :: String
, year :: Integer }
deriving (Eq, Show)

-- The Null is still not great, but


-- we're leaving it in to make a point
data Automobile = Null
| Automobile Car
deriving (Eq, Show)
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

/PX JG XF BUUFNQU UP EP TPNFUIJOH TJMMZ UIF UZQF TZTUFN


DBUDIFT VT

Prelude> make Null

Couldn't match expected type ‘Car’


with actual type ‘Automobile’
In the first argument of ‘make’, namely ‘Null’
In the expression: make Null

*O )BTLFMM XF XBOU UIF UZQFDIFDLFS UP DBUDI VT EPJOH UIJOHT


XSPOH TP XF DBO ƶY JU CFGPSF QSPCMFNT NVMUJQMZ BOE UIJOHT HP
XSPOH BU SVOUJNF #VU UIF UZQFDIFDLFS DBO CFTU IFMQ UIPTF
XIP IFMQ UIFNTFMWFT

 'VODUJPO UZQF JT FYQPOFOUJBM


*O UIF BSJUINFUJD PG DBMDVMBUJOH JOIBCJUBOUT PG UZQFT GVODUJPO
UZQF JT UIF FYQPOFOU PQFSBUPS (JWFO B GVODUJPO a -> b XF DBO
DBMDVMBUF UIF JOIBCJUBOUT XJUI UIF GPSNVMB ԑռ 
4P JG ԑ BOE Ԑ BSF Bool UIFO ϵ JT IPX ZPV DPVME FYQSFTT UIF
OVNCFS PG JOIBCJUBOUT JO B GVODUJPO PG Bool -> Bool 4JNJMBSMZ
B GVODUJPO PG Bool UP TPNFUIJOH PG  JOIBCJUBOUT XPVME CF ϵ
BOE UIVT IBWF OJOF QPTTJCMF JNQMFNFOUBUJPOT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

a -> b -> c

(c ^ b) ^ a

-- given arithmetic laws, can be rewritten as

c ^ (b * a)

&BSMJFS XF JEFOUJƶFE UIF UZQF (Bool, Bool) BT IBWJOH GPVS


JOIBCJUBOUT 5IJT DBO CF EFUFSNJOFE CZ FJUIFS XSJUJOH PVU BMM
UIF QPTTJCMF VOJRVF JOIBCJUBOUT PS NPSF FBTJMZ CZ EPJOH UIF
BSJUINFUJD PG (1 + 1) * (1 + 1) /FYU XFƊMM TFF UIBU UIF UZQF PG
GVODUJPOT (->) JT JO UIF BMHFCSB PG UZQFT UIF FYQPOFOUJBUJPO
PQFSBUPS 8FƊMM VTF B EBUBUZQF XJUI UISFF DBTFT CFDBVTF Bool
IBT POF EJƸDVMUZ UXP QMVT UXP UXP UJNFT UXP BOE UXP UP
UIF QPXFS PG UXP BMM FRVBM UIF TBNF UIJOH -FUƊT SFWJFX UIF
BSJUINFUJD PG TVN UZQFT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

data Quantum =
Yes
| No
| Both
deriving (Eq, Show)

-- 3 + 3
quantSum1 :: Either Quantum Quantum
quantSum1 = Right Yes

quantSum2 :: Either Quantum Quantum


quantSum2 = Right No

quantSum3 :: Either Quantum Quantum


quantSum3 = Right Both

quantSum4 :: Either Quantum Quantum


quantSum4 = Left Yes
-- You can fill in the next two.

"OE OPX UIF BSJUINFUJD PG QSPEVDU UZQFT


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- 3 * 3
quantProd1 :: (Quantum, Quantum)
quantProd1 = (Yes, Yes)

quantProd2 :: (Quantum, Quantum)


quantProd2 = (Yes, No)

quantProd3 :: (Quantum, Quantum)


quantProd3 = (Yes, Both)

quantProd4 :: (Quantum, Quantum)


quantProd4 = (No, Yes)

quantProd5 :: (Quantum, Quantum)


quantProd5 = (No, No)

quantProd6 :: (Quantum, Quantum)


quantProd6 = (No, Both)

quantProd7 :: (Quantum, Quantum)


quantProd7 = (Both, Yes)
-- You can determine the final two.

"OE OPX B GVODUJPO UZQF &BDI QPTTJCMF VOJRVF JNQMFNFO


UBUJPO PG UIF GVODUJPO JT BO JOIBCJUBOU
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- 3 ^ 3

quantFlip1 :: Quantum -> Quantum


quantFlip1 Yes = Yes
quantFlip1 No = Yes
quantFlip1 Both = Yes

quantFlip2 :: Quantum -> Quantum


quantFlip2 Yes = Yes
quantFlip2 No = Yes
quantFlip2 Both = No

quantFlip3 :: Quantum -> Quantum


quantFlip3 Yes = Yes
quantFlip3 No = Yes
quantFlip3 Both = Both
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

quantFlip4 :: Quantum -> Quantum


quantFlip4 Yes = Yes
quantFlip4 No = No
quantFlip4 Both = Yes

quantFlip5 :: Quantum -> Quantum


quantFlip5 Yes = Yes
quantFlip5 No = Both
quantFlip5 Both = Yes

quantFlip6 :: Quantum -> Quantum


quantFlip6 Yes = No
quantFlip6 No = Yes
quantFlip6 Both = Yes
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

quantFlip7 :: Quantum -> Quantum


quantFlip7 Yes = Both
quantFlip7 No = Yes
quantFlip7 Both = Yes

quantFlip8 :: Quantum -> Quantum


quantFlip8 Yes = Both
quantFlip8 No = Yes
quantFlip8 Both = No

quantFlip9 :: Quantum -> Quantum


quantFlip9 Yes = Both
quantFlip9 No = No
quantFlip9 Both = No

quantFlip10 :: Quantum -> Quantum


quantFlip10 Yes = Both
quantFlip10 No = No
quantFlip10 Both = Both

-- You can figure out the remaining


-- possibilities yourself.
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

&YQPOFOUJBUJPO JO XIBU PSEFS


$POTJEFS UIF GPMMPXJOH GVODUJPO

convert :: Quantum -> Bool


convert = undefined

"DDPSEJOH UP UIF FRVBMJUZ PG a -> b BOE ԑռ UIFSF TIPVME CF ϯ


PS  JNQMFNFOUBUJPOT PG UIJT GVODUJPO %PFT UIJT IPME 8SJUF
JU PVU BOE QSPWF JU GPS ZPVSTFMG

&YFSDJTFT 5IF 2VBE


%FUFSNJOF IPX NBOZ VOJRVF JOIBCJUBOUT FBDI UZQF IBT
4VHHFTUJPO KVTU EP UIF BSJUINFUJD VOMFTT ZPV XBOU UP WFSJGZ
8SJUJOH UIFN PVU HFUT UFEJPVT RVJDLMZ

 data Quad =
One
| Two
| Three
| Four
deriving (Eq, Show)

-- how many different forms can this take?


eQuad :: Either Quad Quad
eQuad = ???
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

 prodQuad :: (Quad, Quad)

 funcQuad :: Quad -> Quad

 prodTBool :: (Bool, Bool, Bool)

 gTwo :: Bool -> Bool -> Bool

 )JOU  EJHJU OVNCFS

fTwo :: Bool -> Quad -> Quad

 )JHIFSLJOEFE EBUBUZQFT


:PV NBZ SFDBMM XF EJTDVTTFE LJOET FBSMJFS JO UIJT DIBQUFS ,JOET
BSF UIF UZQFT PG UZQF DPOTUSVDUPST QSJNBSJMZ FODPEJOH UIF
OVNCFS PG BSHVNFOUT UIFZ UBLF 5IF EFGBVMU LJOE JO )BTLFMM JT
* ,JOE TJHOBUVSFT XPSL MJLF UZQF TJHOBUVSFT VTJOH UIF TBNF ::
BOE -> TZOUBY CVU UIFSF BSF POMZ B GFX LJOET BOE ZPVƊMM NPTU
PǒFO TFF *
,JOET BSF OPU UZQFT VOUJM UIFZ BSF GVMMZ BQQMJFE 0OMZ UZQFT
IBWF JOIBCJUBOUT BU UIF UFSN MFWFM 5IF LJOE * -> * JT XBJUJOH
GPS B TJOHMF * CFGPSF JU JT GVMMZ BQQMJFE 5IF LJOE * -> * -> *
NVTU CF BQQMJFE UXJDF CFGPSF JU XJMM CF B SFBM UZQF 5IJT JT
LOPXO BT B IJHIFSLJOEFE UZQF -JTUT GPS FYBNQMF BSF IJHIFS
LJOEFE EBUBUZQFT JO )BTLFMM
#FDBVTF UZQFT DBO CF HFOFSJDBMMZ QPMZNPSQIJD CZ UBLJOH
UZQF BSHVNFOUT UIFZ DBO CF BQQMJFE BU UIF UZQF MFWFM
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

-- Silly polymorphic product type


-- this is identical to (a, b, c, d)
data Silly a b c d = MkSilly a b c d deriving Show

-- in GHCi
Prelude> :kind Silly
Silly :: * -> * -> * -> * -> *

Prelude> :kind Silly Int


Silly Int :: * -> * -> * -> *

Prelude> :kind Silly Int String


Silly Int String :: * -> * -> *

Prelude> :kind Silly Int String Bool


Silly Int String Bool :: * -> *

Prelude> :kind Silly Int String Bool String


Silly Int String Bool String :: *

-- Identical to (a, b, c, d)
Prelude> :kind (,,,)
(,,,) :: * -> * -> * -> * -> *

Prelude> :kind (Int, String, Bool, String)


(Int, String, Bool, String) :: *
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

(FUUJOH DPNGPSUBCMF XJUI IJHIFSLJOEFE UZQFT JT JNQPSUBOU


BT UZQF BSHVNFOUT QSPWJEF B HFOFSJD XBZ UP FYQSFTT B ƌIPMFƍ
UP CF ƶMMFE CZ DPOTVNFST PG ZPVS EBUBUZQF MBUFS 5BLF UIF
GPMMPXJOH BT BO FYBNQMF GSPN B MJCSBSZ POF PG UIF BVUIPST
NBJOUBJOT DBMMFE #MPPEIPVOE

data EsResultFound a =
EsResultFound { _version :: DocVersion
, _source :: a
} deriving (Eq, Show)

8F LOPX UIBU UIJT QBSUJDVMBS LJOE PG SFTQPOTF GSPN &MBTUJD


TFBSDI XJMM JODMVEF B DocVersion WBMVF TP UIBUƊT CFFO BTTJHOFE B
UZQF 0O UIF PUIFS IBOE _source IBT UZQF Ԑ CFDBVTF XF IBWF
OP JEFB XIBU UIF TUSVDUVSF PG UIF EPDVNFOUT UIFZƊSF QVMMJOH
GSPN &MBTUJDTFBSDI MPPL MJLF *O QSBDUJDF XF EP OFFE UP CF BCMF
UP EP TPNFUIJOH XJUI UIBU WBMVF PG UZQF Ԑ 5IF UIJOH XF XJMM
XBOU UP EP XJUI JU ƈ UIF XBZ XF XJMM DPOTVNF PS VTF UIBU EBUB
ƈ XJMM VTVBMMZ CF B FromJSON UZQFDMBTT JOTUBODF GPS EFTFSJBMJ[JOH
+40/ EBUB JOUP B )BTLFMM EBUBUZQF #VU JO )BTLFMM XF EP OPU
DPOWFOUJPOBMMZ QVU DPOTUSBJOUT PO EBUBUZQFT 5IBU JT XF EPOƊU
XBOU UP DPOTUSBJO UIBU QPMZNPSQIJD Ԑ JO UIF EBUBUZQF 5IF
FromJSON UZQFDMBTT XJMM MJLFMZ BTTVNJOH UIBUƊT XIBU JT OFFEFE JO

http://hackage.haskell.org/package/bloodhound *G ZPV BSF OPU B QSPHSBNNFS BOE EP
OPU LOPX XIBU &MBTUJDTFBSDI BOE +40/ BSF USZ OPU UP XPSSZ UPP NVDI BCPVU UIF TQFDJƶDT
&MBTUJDTFBSDI JT B TFBSDI FOHJOF BOE +40/ JT B OPUBUJPO GPS USBOTNJUUJOH EBUB FTQFDJBMMZ
CFUXFFO TFSWFST BOE XFC BQQMJDBUJPOT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

B HJWFO DPOUFYU
DPOTUSBJO UIF WBSJBCMF JO UIF UZQF TJHOBUVSF T

GPS UIF GVODUJPO T


UIBU XJMM QSPDFTT UIJT EBUB
"DDPSEJOHMZ UIF FromJSON UZQFDMBTT JOTUBODF GPS EsResultFound
SFRVJSFT B FromJSON JOTUBODF GPS UIBU Ԑ

instance (FromJSON a) => FromJSON (EsResultFound a) where


parseJSON (Object v) = EsResultFound <$>
v .: "_version" <*>
v .: "_source"
parseJSON _ = empty

"T ZPV DBO IPQFGVMMZ TFF GSPN UIJT CZ OPU GVMMZ BQQMZJOH
UIF UZQF ƈ CZ MFBWJOH JU IJHIFSLJOEFE ƈ TQBDF JT MFǒ GPS UIF
UZQF PG UIF SFTQPOTF UP WBSZ GPS UIF ƌIPMFƍ UP CF ƶMMFE JO CZ
UIF FOE VTFS

 -JTUT BSF QPMZNPSQIJD


8IBU NBLFT B MJTU QPMZNPSQIJD *O XIBU XBZ DBO JU UBLF NBOZ
GPSNT 8IBU NBLFT UIFN QPMZNPSQIJD JT UIBU MJTUT JO )BTLFMM
DBO DPOUBJO WBMVFT PG BOZ UZQF :PV EP OPU IBWF BO Ԑ VOUJM UIF
MJTU UZQFƊT UZQF BSHVNFOU IBT CFFO GVMMZ BQQMJFE

-- Haskell definition of lists aka []


data [] a = [] | a : [a]
-- [1] [2] [3] [4] [5] [6]
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

 5ZQF DPOTUSVDUPS GPS MJTU IBT TQFDJBM [] TZOUBY

 4JOHMF UZQF BSHVNFOU UP [] 5IJT JT UIF UZQF PG WBMVF PVS


MJTU DPOUBJOT

 /JM  FNQUZ MJTU WBMVF DPOTUSVDUPS BHBJO XJUI UIF TQFDJBM


<> TZOUBY <> NBSLT UIF FOE PG UIF MJTU

 " TJOHMF WBMVF PG UZQF Ԑ

 : JT BO JOƶY EBUB DPOTUSVDUPS *U JT B QSPEVDU PG Ԑ <> BOE


[a] <>

 5IF SFTU PG PVS MJTU

*OƶY UZQF BOE EBUB DPOTUSVDUPST 8IFO XF HJWF BO PQFSBUPS


B OPOBMQIBOVNFSJD OBNF JU JT JOƶY CZ EFGBVMU 'PS FYBN
QMF BMM UIF OPOBMQIBOVNFSJD BSJUINFUJD GVODUJPOT BSF JOƶY
PQFSBUPST XIJMF XF IBWF TPNF BMQIBOVNFSJD BSJUINFUJD GVOD
UJPOT TVDI BT div BOE mod UIBU BSF QSFƶY CZ EFGBVMU 4P GBS
XFƊWF POMZ TFFO BMQIBOVNFSJD EBUB DPOTUSVDUPST FYDFQU GPS
UIJT DPOT DPOTUSVDUPS JO UIF MJTU UZQF CVU UIF TBNF SVMF BQQMJFT
UP UIFN
"OZ PQFSBUPS UIBU TUBSUT XJUI B DPMPO :
NVTU CF BO JO
ƶY UZQF PS EBUB DPOTUSVDUPS "MM JOƶY EBUB DPOTUSVDUPST NVTU
TUBSU XJUI B DPMPO 5IF UZQF DPOTUSVDUPS PG GVODUJPOT (->) JT
UIF POMZ JOƶY UZQF DPOTUSVDUPS UIBU EPFTOƊU TUBSU XJUI B DPMPO
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

"OPUIFS FYDFQUJPO JT UIBU UIFZ DBOOPU CF :: BT UIJT TZOUBY JT


SFTFSWFE GPS UZQF BTTFSUJPOT
5IF MJTU UZQF JO Prelude IBT BMSFBEZ UBLFO UIF MPOF DPMPO
BT UIF EBUB DPOTUSVDUPS GPS UIF DPOT DFMMT CVU ZPV DBO BEE
OPOBMQIBOVNFSJD DIBSBDUFST UP HFU ZPVS PXO VOJRVF JOƶY
UZQF PS EBUB DPOTUSVDUPS )FSFƊT BO FYBNQMF PG BO JOƶY EBUB
DPOTUSVDUPS

data Product a b =
a :&: b
deriving (Eq, Show)

5IFO VTJOH JU JO UIF 3&1-

Prelude> 1 :&: 2
1 :&: 2
Prelude> :t 1 :&: 2
1 :&: 2 :: (Num a, Num b) => Product a b

" WBMVF PG UZQF Product XPVME CF B QSPEVDU PG UXP BSHVNFOUT


POF PG UZQF Ԑ BOE POF PG UZQF ԑ
8IFUIFS PS OPU ZPV DIPPTF UP VTF JOƶY EBUB DPOTUSVDUPST
UZQF DPOTUSVDUPST PS UZQFDMBTT OBNFT JT EPXO UP BFTUIFUJD
QSFGFSFODF
*O UIF GPMMPXJOH FYBNQMF XFƊMM EFƶOF UIF MJTU UZQF XJUIPVU
VTJOH BO JOƶY DPOTUSVDUPS
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- Same type, but redefined with slightly different syntax


data List a = Nil | Cons a (List a)
-- [1] [2] [3] [5] [4] [6]

 5IF List UZQF DPOTUSVDUPS

 5IF Ԑ UZQF QBSBNFUFS UP List

 /JM  FNQUZ MJTU WBMVF XIJDI BMTP NBSLT UIF FOE PG B MJTU

 " TJOHMF WBMVF PG UZQF Ԑ JO UIF Cons QSPEVDU

 5IF Cons DPOTUSVDUPS QSPEVDU PG Ԑ BOE List a

 5IF SFTU PG PVS MJTU

)PX EP XF VTF PVS List UZQF

-- from GHCi
Prelude> let nil = Nil

-- the type parameter isn't applied because


-- Nil by itself doesn't tell the type inference
-- what the List contains.
Prelude> :t nil
nil :: List a

Prelude> let oneItem = (Cons "woohoo!" Nil)


Prelude> :t oneItem
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

oneItem :: List [Char]

"OE IPX BSF PVS MJTU UZQFT LJOEFE

Prelude> :kind List


List :: * -> *
Prelude> :kind []
[] :: * -> *

Prelude> :kind List Int


List Int :: *
Prelude> :kind [Int]
[Int] :: *

.VDI BT XF DBO SFGFS UP UIF GVODUJPO not CFGPSF XFƊWF BQ


QMJFE JUT BSHVNFOU XF DBO SFGFS UP UIF UZQF DPOTUSVDUT List
BOE [] CFGPSF XFƊWF BQQMJFE UIFJS BSHVNFOU

Prelude> :t not
not :: Bool -> Bool
Prelude> :t not True
not True :: Bool

Prelude> :k []
[] :: * -> *
Prelude> :k [Int]
[Int] :: *
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

5IF EJƵFSFODF JT UIBU UIF BSHVNFOU PG not JT BOZ WBMVF PG


UZQF Bool BOE UIF BSHVNFOU PG [] JT BOZ UZQF PG LJOE * 4P
UIFZƊSF TJNJMBS CVU UZQF DPOTUSVDUPST BSF GVODUJPOT POF MFWFM
VQ TUSVDUVSJOH UIJOHT UIBU DBOOPU FYJTU BU SVOUJNF ƈ JUƊT QVSFMZ
TUBUJD BOE EFTDSJCFT UIF TUSVDUVSF PG ZPVS UZQFT

 #JOBSZ 5SFF


/PX XF UVSO PVS BUUFOUJPO UP B UZQF TJNJMBS UP MJTU 5IF UZQF
DPOTUSVDUPS GPS CJOBSZ USFFT DBO UBLF BO BSHVNFOU BOE JU JT
BMTP SFDVSTJWF MJLF MJTUT

data BinaryTree a =
Leaf
| Node (BinaryTree a) a (BinaryTree a)
deriving (Eq, Ord, Show)

5IJT USFF IBT B WBMVF PG UZQF Ԑ BU FBDI OPEF &BDI OPEF


DPVME CF B UFSNJOBM OPEF DBMMFE B MFBG PS JU DPVME CSBODI BOE
IBWF UXP TVCUSFFT 5IF TVCUSFFT BSF BMTP PG UZQF BinaryTree a
TP UIJT UZQF JT SFDVSTJWF &BDI CJOBSZ USFF DBO TUPSF ZFU BOPUIFS
CJOBSZ USFF XIJDI BMMPXT GPS USFFT PG BSCJUSBSZ EFQUI
*O TPNF DBTFT CJOBSZ USFFT DBO CF NPSF FƸDJFOU GPS TUSVD
UVSJOH BOE BDDFTTJOH EBUB UIBO B MJTU FTQFDJBMMZ JG ZPV LOPX
IPX UP PSEFS ZPVS WBMVFT JO B XBZ UIBU MFUT ZPV LOPX XIFUIFS
UP MPPL ƌMFǒƍ PS ƌSJHIUƍ UP ƶOE XIBU ZPV XBOU 0O UIF PUIFS
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

IBOE B USFF UIBU POMZ CSBODIFT UP UIF SJHIU JT JOEJTUJOHVJTIBCMF


GSPN BO PSEJOBSZ MJTU 'PS OPX XF XPOƊU DPODFSO PVSTFMWFT
UPP NVDI XJUI UIJT BT XFƊMM UBML BCPVU UIF QSPQFS BQQMJDBUJPO
PG EBUB TUSVDUVSFT MBUFS *OTUFBE ZPVƊSF HPJOH UP XSJUF TPNF
GVODUJPOT GPS QSPDFTTJOH BinaryTree WBMVFT

*OTFSUJOH JOUP USFFT


5IF ƶSTU UIJOH UP CF BXBSF PG JT UIBU XF OFFE Ord JO PSEFS UP IBWF
FOPVHI JOGPSNBUJPO BCPVU PVS WBMVFT UP LOPX IPX UP BSSBOHF
UIFN JO PVS USFF "DDPSEJOHMZ JG TPNFUIJOH JT MPXFS XF XBOU
UP JOTFSU JU TPNFXIFSF PO UIF MFǒIBOE QBSU PG PVS USFF *G JUƊT
HSFBUFS UIBO UIF DVSSFOU OPEF WBMVF JU TIPVME HP TPNFXIFSF
UP UIF SJHIU -Fǒ MFTTFS SJHIU HSFBUFS JT B DPNNPO DPOWFOUJPO
GPS BSSBOHJOH CJOBSZ USFFT ƈ JU DPVME CF UIF PQQPTJUF BOE OPU
SFBMMZ DIBOHF BOZUIJOH CVU UIJT NBUDIFT PVS VTVBM JOUVJUJPOT
PG PSEFSJOH BT XF EP XJUI TBZ OVNCFS MJOFT 5IF QPJOU JT ZPV
XBOU UP CF BCMF UP LOPX XIFSF UP MPPL JO UIF USFF GPS WBMVFT
HSFBUFS PS MFTT UIBO UIF DVSSFOU POF ZPVƊSF MPPLJOH BU
0VS insert GVODUJPO XJMM JOTFSU B WBMVF JOUP B USFF PS JG OP
USFF FYJTUT ZFU HJWF VT B NFBOT PG CVJMEJOH B USFF CZ JOTFSUJOH
WBMVFT *UƊT JNQPSUBOU UP SFNFNCFS UIBU EBUB JT JNNVUBCMF JO
)BTLFMM 8F EP OPU BDUVBMMZ JOTFSU B WBMVF JOUP BO FYJTUJOH USFF
FBDI UJNF XF XBOU UP JOTFSU B WBMVF JOUP UIF EBUB TUSVDUVSF XF
CVJME B XIPMF OFX USFF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

insert' :: Ord a => a -> BinaryTree a -> BinaryTree a


insert' b Leaf = Node Leaf b Leaf
insert' b (Node left a right)
| b == a = Node left a right
| b < a = Node (insert' b left) a right
| b > a = Node left a (insert' b right)

5IF CBTF DBTF JO PVS insert' GVODUJPO TFSWFT B DPVQMF QVS


QPTFT *U IBOEMFT JOTFSUJOH JOUP BO FNQUZ USFF -FBG
BOE CFHJO
OJOH UIF DPOTUSVDUJPO PG B OFX USFF BOE BMTP UIF DBTF PG IBWJOH
SFBDIFE UIF CPUUPN PG B NVDI MBSHFS USFF 5IF TJNQMJDJUZ IFSF
MFUT VT JHOPSF BOZ JOFTTFOUJBM EJƵFSFODFT CFUXFFO UIPTF UXP
DBTFT

-- Leaf being our "empty tree" case

Prelude> let t1 = insert' 0 Leaf


Prelude> t1
Node Leaf 0 Leaf

Prelude> let t2 = insert' 3 t1


Prelude> t2
Node Leaf 0 (Node Leaf 3 Leaf)

Prelude> let t3 = insert' 5 t2


Prelude> t3
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

Node Leaf 0 (Node Leaf 3 (Node Leaf 5 Leaf))

8F XJMM FYBNJOF CJOBSZ USFFT BOE UIFJS QSPQFSUJFT MBUFS JO


UIF CPPL 'PS OPX XF XBOU UP GPDVT OPU PO UIF QSPQFSUJFT PG
CJOBSZ USFFT UIFNTFMWFT CVU NFSFMZ PO UIF TUSVDUVSF PG UIFJS
UZQF :PV NJHIU ƶOE UIF GPMMPXJOH FYFSDJTFT USJDLZ PS UFEJPVT
CVU UIFZ XJMM EFFQFO ZPVS JOUVJUJPO GPS IPX SFDVSTJWF UZQFT
XPSL

8SJUF NBQ GPS #JOBSZ5SFF


(JWFO UIF EFƶOJUJPO PG BinaryTree BCPWF XSJUF B NBQ GVODUJPO
GPS UIF EBUB TUSVDUVSF :PV EPOƊU SFBMMZ OFFE UP LOPX BOZUIJOH
BCPVU CJOBSZ USFFT UP XSJUF UIFTF GVODUJPOT 5IF TUSVDUVSF
JOIFSFOU JO UIF EFƶOJUJPO PG UIF UZQF JT BMM ZPV OFFE +VTU XSJUF
UIF SFDVSTJWF GVODUJPOT BOE HFU JU EPOF
/P TQFDJBM BMHPSJUINT BSF OFFEFE BOE XF EPOƊU FYQFDU ZPV
UP LFFQ UIF USFF CBMBODFE PS PSEFSFE "MTP SFNFNCFS UIBU
XFƊWF OFWFS PODF NVUBUFE BOZUIJOH 8FƊWF POMZ CVJMU OFX
WBMVFT GSPN JOQVU EBUB (JWFO UIBU XIFO ZPV HP UP JNQMFNFOU
mapTree ZPVƊSF OPU DIBOHJOH BO FYJTUJOH USFF ƈ ZPVƊSF CVJMEJOH
B OFX POF CBTFE PO BO FYJTUJOH POF KVTU MJLF XIFO ZPV BSF
NBQQJOH GVODUJPOT PWFS MJTUT

$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- filling in some details to help you along


-- Note, you do *not* need to use insert' for this.
-- Retain the original structure of the tree.

mapTree :: (a -> b) -> BinaryTree a -> BinaryTree b


mapTree _ Leaf = Leaf
mapTree f (Node left a right) =
Node undefined undefined undefined

testTree' :: BinaryTree Integer


testTree' =
Node (Node Leaf 3 Leaf) 1 (Node Leaf 4 Leaf)

mapExpected =
Node (Node Leaf 4 Leaf) 2 (Node Leaf 5 Leaf)

-- acceptance test for mapTree


mapOkay =
if mapTree (+1) testTree' == mapExpected
then print "yup okay!"
else error "test failed!"

-- hints for implementing mapTree below this code block

5IF ƶSTU QBUUFSO NBUDI JO PVS mapTree GVODUJPO JT UIF CBTF


$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

DBTF XIFSF XF IBWF B Leaf WBMVF 8F DBOƊU BQQMZ UIF ԕ UIFSF


CFDBVTF XF EPOƊU IBWF BO Ԑ TP XF JHOPSFE JU 4JODF XF IBWF
UP SFUVSO B WBMVF PG UZQF BinaryTree b XIBUFWFS IBQQFOT XF
SFUVSO B Leaf WBMVF
8F SFUVSO B Node JO UIF TFDPOE QBUUFSO NBUDI PG PVS mapTree
GVODUJPO /PUF UIBU UIF Node EBUB DPOTUSVDUPS UBLFT UISFF BSHV
NFOUT

Prelude> :t Node
Node :: BinaryTree a -> a -> BinaryTree a -> BinaryTree a

4P ZPV OFFE UP QBTT JU NPSF BinaryTree B TJOHMF WBMVF BOE


NPSF BinaryTree :PV IBWF UIF GPMMPXJOH UFSNT BWBJMBCMF UP
ZPV

 f :: (a -> b)

 left :: BinaryTree a

 a :: a

 right :: BinaryTree a

 mapTree :: (a -> b) -> BinaryTree a -> BinaryTree b

/PX UIF Node SFUVSO OFFET UP IBWF B WBMVF PG UZQF ԑ BOE


BinaryTree WBMVFT XJUI UZQF ԑ JOTJEF UIFN :PV IBWF UXP GVOD
UJPOT BU ZPVS EJTQPTBM 0OF HFUT ZPV (a -> b) UIF PUIFS NBQT
BinaryTreeT PG UZQF Ԑ JOUP BinaryTreeT PG UZQF ԑ (FU ƊFN UJHFS
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

" GFX TVHHFTUJPOT UIBU NJHIU IFMQ ZPV XJUI UIJT FYFSDJTF

 4QMJU PVU UIF QBUUFSOT ZPVS GVODUJPO TIPVME NBUDI PO ƶSTU

 *NQMFNFOU UIF CBTF DBTF ƶSTU

 5SZ NBOVBMMZ XSJUJOH PVU UIF TUFQT PG SFDVSTJPO BU ƶSTU


UIFO DPMMBQTF UIFN JOUP B TJOHMF TUFQ UIBU JT SFDVSTJWF

$POWFSU CJOBSZ USFFT UP MJTUT


8SJUF GVODUJPOT UP DPOWFSU BinaryTree WBMVFT UP MJTUT .BLF
DFSUBJO ZPVS JNQMFNFOUBUJPO QBTTFT UIF UFTUT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

preorder :: BinaryTree a -> [a]


preorder = undefined

inorder :: BinaryTree a -> [a]


inorder = undefined

postorder :: BinaryTree a -> [a]


postorder = undefined

testTree :: BinaryTree Integer


testTree = Node (Node Leaf 1 Leaf) 2 (Node Leaf 3 Leaf)

testPreorder :: IO ()
testPreorder =
if preorder testTree == [2, 1, 3]
then putStrLn "Preorder fine!"
else putStrLn "Bad news bears."

testInorder :: IO ()
testInorder =
if inorder testTree == [1, 2, 3]
then putStrLn "Inorder fine!"
else putStrLn "Bad news bears."

testPostorder :: IO ()
testPostorder =
if postorder testTree == [1, 3, 2]
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

8SJUF GPMES GPS #JOBSZ5SFF


(JWFO UIF EFƶOJUJPO PG BinaryTree XF IBWF QSPWJEFE XSJUF B
DBUBNPSQIJTN GPS UIF CJOBSZ USFFT

-- any traversal order is fine


foldTree :: (a -> b -> b) -> b -> BinaryTree a -> b

 $IBQUFS &YFSDJTFT


.VMUJQMF DIPJDF
 (JWFO UIF GPMMPXJOH EBUBUZQF

data Weekday =
Monday
| Tuesday
| Wednesday
| Thursday
| Friday

XF DBO TBZ

B
Weekday JT B UZQF XJUI ƶWF EBUB DPOTUSVDUPST
C
Weekday JT B USFF XJUI ƶWF CSBODIFT
D
Weekday JT B QSPEVDU UZQF
E
Weekday UBLFT ƶWF BSHVNFOUT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

 BOE XJUI UIF TBNF EBUBUZQF EFƶOJUJPO JO NJOE XIBU JT


UIF UZQF PG UIF GPMMPXJOH GVODUJPO f

f Friday = "Miller Time"

B
f :: [Char]
C
f :: String -> String
D
f :: Weekday -> String
E
f :: Day -> Beer

 5ZQFT EFƶOFE XJUI UIF data LFZXPSE

B
NVTU IBWF BU MFBTU POF BSHVNFOU
C
NVTU CFHJO XJUI B DBQJUBM MFUUFS
D
NVTU CF QPMZNPSQIJD
E
DBOOPU CF JNQPSUFE GSPN NPEVMFT

 5IF GVODUJPO g xs = xs !! (length xs - 1)

B
JT SFDVSTJWF BOE NBZ OPU UFSNJOBUF
C
EFMJWFST UIF IFBE PG xs
D
EFMJWFST UIF ƶOBM FMFNFOU PG xs
E
IBT UIF TBNF UZQF BT xs
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

$JQIFST
*O UIF -JTUT DIBQUFS ZPV XSPUF B $BFTBS DJQIFS /PX XF XBOU
UP FYQBOE PO UIBU JEFB CZ XSJUJOH B 7JHFO¨SF DJQIFS " 7J
HFO¨SF DJQIFS JT BOPUIFS TVCTUJUVUJPO DJQIFS CBTFE PO B $BFTBS
DJQIFS CVU JU VTFT B TFSJFT PG $BFTBS DJQIFST GPS QPMZBMQIBCFUJD
TVCTUJUVUJPO 5IF TVCTUJUVUJPO GPS FBDI MFUUFS JO UIF QMBJOUFYU
JT EFUFSNJOFE CZ B ƶYFE LFZXPSE
4P GPS FYBNQMF JG ZPV XBOU UP FODPEF UIF NFTTBHF ƌNFFU
BU EBXO ƍ UIF ƶSTU TUFQ JT UP QJDL B LFZXPSE UIBU XJMM EFUFSNJOF
XIJDI $BFTBS DJQIFS UP VTF 8FƊMM VTF UIF LFZXPSE ƌ"--:ƍ
IFSF :PV SFQFBU UIF LFZXPSE GPS BT NBOZ DIBSBDUFST BT UIFSF
BSF JO ZPVS PSJHJOBM NFTTBHF

MEET AT DAWN
ALLY AL LYAL

/PX UIF OVNCFS PG SJHIUXBSE TIJǒT UP NBLF UP FODPEF FBDI


DIBSBDUFS JT TFU CZ UIF DIBSBDUFS PG UIF LFZXPSE UIBU MJOFT VQ
XJUI JU 5IF Ɗ"Ɗ NFBOT B TIJǒ PG  TP UIF JOJUJBM . XJMM SFNBJO
. #VU UIF Ɗ-Ɗ GPS PVS TFDPOE DIBSBDUFS TFUT B SJHIUXBSE TIJǒ
PG  TP Ɗ&Ɗ CFDPNFT Ɗ1Ɗ "OE TP PO TP ƌNFFU BU EBXOƍ FODPEFE
XJUI UIF LFZXPSE ƌ"--:ƍ CFDPNFT ƌ.113 "& 0:8:ƍ
-JLF UIF $BFTBS DJQIFS ZPV DBO ƶOE BMM LJOET PG SFTPVSDFT UP
IFMQ ZPV VOEFSTUBOE UIF DJQIFS BOE BMTP NBOZ FYBNQMFT XSJU
UFO JO )BTLFMM $POTJEFS VTJOH B DPNCJOBUJPO PG chr ord BOE
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

mod BHBJO QPTTJCMZ WFSZ TJNJMBS UP XIBU ZPV VTFE GPS XSJUJOH
UIF PSJHJOBM $BFTBS DJQIFS

"TQBUUFSOT
ƌ"TQBUUFSOTƍ JO )BTLFMM BSF B OJǒZ XBZ UP CF BCMF UP QBUUFSO
NBUDI PO QBSU PG TPNFUIJOH BOE TUJMM SFGFS UP UIF FOUJSF PSJHJOBM
WBMVF 4PNF FYBNQMFT

f :: Show a => (a, b) -> IO (a, b)


f t@(a, _) = do
print a
return t

)FSF XF QBUUFSONBUDIFE PO B UVQMF TP XF DPVME HFU BU UIF


ƶSTU WBMVF GPS QSJOUJOH CVU VTFE UIF @ TZNCPM UP JOUSPEVDF B
CJOEJOH OBNFE t JO PSEFS UP SFGFS UP UIF XIPMF UVQMF SBUIFS
UIBO KVTU B QBSU

Prelude> f (1, 2)
1
(1,2)

8F DBO VTF BTQBUUFSOT XJUI QBUUFSO NBUDIJOH PO BSCJUSBSZ


EBUB DPOTUSVDUPST XIJDI JODMVEFT MJTUT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

doubleUp :: [a] -> [a]


doubleUp [] = []
doubleUp xs@(x:_) = x : xs

Prelude> doubleUp []
[]
Prelude> doubleUp [1]
[1,1]
Prelude> doubleUp [1, 2]
[1,1,2]
Prelude> doubleUp [1, 2, 3]
[1,1,2,3]

6TF BTQBUUFSOT JO JNQMFNFOUJOH UIF GPMMPXJOH GVODUJPOT

 5IJT TIPVME SFUVSO 5SVF JG BOE POMZ JG


BMM UIF WBMVFT JO
UIF ƶSTU MJTU BQQFBS JO UIF TFDPOE MJTU UIPVHI UIFZ OFFE
OPU CF DPOUJHVPVT

isSubsequenceOf :: (Eq a) => [a] -> [a] -> Bool

5IF GPMMPXJOH BSF FYBNQMFT PG IPX UIJT GVODUJPO TIPVME


XPSL

Prelude> isSubsequenceOf "blah" "blahwoot"


True
Prelude> isSubsequenceOf "blah" "wootblah"
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34& 

True
Prelude> isSubsequenceOf "blah” "wboloath"
True
Prelude> isSubsequenceOf "blah" "wootbla"
False

 4QMJU B TFOUFODF JOUP XPSET UIFO UVQMF FBDI XPSE XJUI UIF
DBQJUBMJ[FE GPSN PG FBDI

capitalizeWords :: String -> [(String, String)]

Prelude> capitalizeWords "hello world"


[("hello", "Hello"), ("world", "World")]

-BOHVBHF FYFSDJTFT
 8SJUF B GVODUJPO UIBU DBQJUBMJ[FT B XPSE

capitalizeWord :: String -> String


capitalizeWord = undefined

&YBNQMF PVUQVU

Prelude> capitalizeWord "Titter"


"Titter"
Prelude> capitalizeWord "titter"
"Titter"
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

 8SJUF B GVODUJPO UIBU DBQJUBMJ[FT TFOUFODFT JO B QBSBHSBQI


3FDPHOJ[F XIFO B OFX TFOUFODF IBT CFHVO CZ DIFDLJOH
GPS QFSJPET 3FVTF UIF DBQJUBMJ[F8PSE GVODUJPO

capitalizeParagraph :: String -> String


capitalizeParagraph = undefined

&YBNQMF SFTVMU ZPV TIPVME HFU GSPN ZPVS GVODUJPO

Prelude> capitalizeParagraph "blah. woot ha."


"Blah. Woot ha."

1IPOF FYFSDJTF
5IJT FYFSDJTF CZ HFPQIG PSJHJOBMMZ GPS )BTLFMM"%BZ 5IBOL
ZPV GPS MFUUJOH VT VTF UIJT FYFSDJTF
3FNFNCFS PMEGBTIJPOFE QIPOF JOQVUT GPS XSJUJOH UFYU
XIFSF ZPV IBE UP QSFTT B CVUUPO NVMUJQMF UJNFT UP HFU EJƵFSFOU
MFUUFST UP DPNF VQ :PV NBZ TUJMM IBWF UP EP UIJT XIFO ZPV USZ
UP TFBSDI GPS B NPWJF UP XBUDI VTJOH ZPVS UFMFWJTJPO SFNPUF
DPOUSPM :PVƊSF HPJOH UP XSJUF DPEF UP USBOTMBUF TFRVFODFT PG
CVUUPO QSFTTFT JOUP TUSJOHT BOE WJDF WFSTB
4P )FSF JT UIF MBZPVU PG UIF QIPOF

-----------------------------------------

https://twitter.com/geophf

https://twitter.com/1haskelladay
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

| 1 | 2 ABC | 3 DEF |
_________________________________________
| 4 GHI | 5 JKL | 6 MNO |
-----------------------------------------
| 7 PQRS | 8 TUV | 9 WXYZ |
-----------------------------------------
| * ^ | 0 + _ | # ., |
-----------------------------------------

8IFSF TUBS
HJWFT ZPV DBQJUBMJ[BUJPO PG UIF MFUUFS ZPVƊSF
XSJUJOH UP ZPVS GSJFOET BOE  JT ZPVS TQBDF CBS 5P SFQSFTFOU
UIF EJHJU JUTFMG ZPV QSFTT UIBU EJHJU PODF NPSF UIBO UIF MFUUFST JU
SFQSFTFOUT *G ZPV QSFTT B CVUUPO POF NPSF UIBO JT SFRVJSFE UP
UZQF UIF EJHJU JU XSBQT BSPVOE UP UIF ƶSTU MFUUFS 'PS FYBNQMF

2 -> 'A'
22 -> 'B'
222 -> 'C'
2222 -> '2'
22222 -> 'A'

4P PO BOE TP GPSUI 8FƊSF HPJOH UP LJDL UIJT BSPVOE

 $SFBUF B EBUB TUSVDUVSF UIBU DBQUVSFT UIF QIPOF MBZPVU


BCPWF 5IF EBUB TUSVDUVSF TIPVME CF BCMF UP FYQSFTT FOPVHI
PG IPX UIF MBZPVU XPSLT UIBU ZPV DBO VTF JU UP EJDUBUF UIF
CFIBWJPS PG UIF GVODUJPOT JO UIF GPMMPXJOH FYFSDJTFT
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- fill in the rest.


data DaPhone = DaPhone

 $POWFSU UIF GPMMPXJOH DPOWFSTBUJPOT JOUP UIF LFZQSFTTFT


SFRVJSFE UP FYQSFTT UIFN 8FƊSF HPJOH UP TVHHFTU UZQFT
BOE GVODUJPOT UP ƶMM JO PSEFS UP BDDPNQMJTI UIF HPBM CVU
UIFZƊSF OPU PCMJHBUPSZ *G ZPV XBOU UP EP JU EJƵFSFOUMZƒZPV
EP ZPV

convo :: [String]
convo =
["Wanna play 20 questions",
"Ya",
"U 1st haha",
"Lol ok. Have u ever tasted alcohol lol",
"Lol ya",
"Wow ur cool haha. Ur turn",
"Ok. Do u think I am pretty Lol",
"Lol ya",
"Haha thanks just making sure rofl ur turn"]
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

-- validButtons = "1234567890*#"
type Digit = Char

-- Valid presses: 1 and up


type Presses = Int

reverseTaps :: DaPhone -> Char -> [(Digit, Presses)]


reverseTaps = undefined
-- assuming the default phone definition
-- 'a' -> [('2', 1)]
-- 'A' -> [('*', 1), ('2', 1)]

cellPhonesDead :: DaPhone
-> String
-> [(Digit, Presses)]
cellPhonesDead = undefined

 )PX NBOZ UJNFT EP EJHJUT OFFE UP CF QSFTTFE GPS FBDI


NFTTBHF

fingerTaps :: [(Digit, Presses)] -> Presses


fingerTaps = undefined

 8IBU XBT UIF NPTU QPQVMBS MFUUFS GPS FBDI NFTTBHF 8IBU
XBT JUT DPTU :PVƊMM XBOU UP DPNCJOF reverseTaps BOE fingerTaps
UP ƶHVSF PVU XIBU JU DPTU JO UBQT reverseTaps JT B MJTU CF
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

DBVTF ZPV OFFE UP QSFTT B EJƵFSFOU CVUUPO JO PSEFS UP HFU


DBQJUBMT

mostPopularLetter :: String -> Char


mostPopularLetter = undefined

 8IBU XBT UIF NPTU QPQVMBS MFUUFS PWFSBMM 8IBU XBT UIF
NPTU QPQVMBS XPSE

coolestLtr :: [String] -> Char


coolestLtr = undefined

coolestWord :: [String] -> String


coolestWord = undefined

)VUUPOƊT 3B[PS
)VUUPOƊT 3B[PS JT B WFSZ TJNQMF FYQSFTTJPO MBOHVBHF UIBU
FYQSFTTFT JOUFHFS MJUFSBMT BOE BEEJUJPO PG WBMVFT JO UIBU FYQSFT
TJPO MBOHVBHF 5IF ƌUSJDLƍ UP JU JT UIBU JUƊT SFDVSTJWF BOE UIF
UXP FYQSFTTJPOT ZPVƊSF TVNNJOH UPHFUIFS DPVME CF MJUFSBMT PS
UIFNTFMWFT GVSUIFS BEEJUJPO PQFSBUJPOT 5IJT TPSU PG EBUBUZQF
JT TUFSFPUZQJDBM PG FYQSFTTJPO MBOHVBHFT VTFE UP NPUJWBUF JEFBT
JO SFTFBSDI QBQFST BOE GVODUJPOBM QFBSMT &WBMVBUJOH PS GPMEJOH
B EBUBUZQF JT BMTP JO TPNF TFOTF XIBU ZPVƊSF EPJOH NPTU PG UIF
UJNF XIJMF QSPHSBNNJOH BOZXBZ

http://www.cs.nott.ac.uk/~pszgmh/bib.html#semantics
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

 :PVS ƶSTU UBTL JT UP XSJUF UIF ƌFWBMƍ GVODUJPO XIJDI SFEVDFT


BO FYQSFTTJPO UP B ƶOBM TVN

data Expr
= Lit Integer
| Add Expr Expr

eval :: Expr -> Integer


eval = error "do it to it"

&YBNQMF PG FYQFDUFE PVUQVU

Prelude> eval (Add (Lit 1) (Lit 9001))


9002

 8SJUF B QSJOUFS GPS UIF FYQSFTTJPOT

printExpr :: Expr -> String


printExpr = undefined

&YQFDUFE PVUQVU

Prelude> printExpr (Add (Lit 1) (Lit 9001))


"1 + 9001"
Prelude> let a1 = Add (Lit 9001) (Lit 1)
Prelude> let a2 = Add a1 (Lit 20001)
Prelude> let a3 = Add (Lit 1) a2
$)"15&3  36-& 5)& 5:1&4 36-& 5)& 6/*7&34&

Prelude> printExpr a3
"1 + 9001 + 1 + 20001"

 %FƶOJUJPOT
 " EBUBUZQF JT IPX XF EFDMBSF BOE DSFBUF EBUB GPS PVS GVOD
UJPOT UP SFDFJWF BT JOQVUT %BUBUZQF EFDMBSBUJPOT CFHJO
XJUI UIF LFZXPSE data " EBUBUZQF JT NBEF VQ PG B UZQF
DPOTUSVDUPS BOE [FSP PS NPSF EBUB DPOTUSVDUPST XIJDI
FBDI IBWF [FSP PS NPSF BSHVNFOUT
$IBQUFS 

4JHOBMJOH BEWFSTJUZ

5IBOL HPPEOFTT XF EPOƊU


IBWF POMZ TFSJPVT
QSPCMFNT CVU SJEJDVMPVT
POFT BT XFMM

&ETHFS 8 %JKLTUSB


$)"15&3  4*(/"-*/( "%7&34*5: 

 4JHOBMJOH BEWFSTJUZ


4PNFUJNFT JUƊT OPU DPOWFOJFOU PS QPTTJCMF GPS FWFSZ WBMVF
JO B EBUBUZQF UP NBLF TFOTF GPS ZPVS QSPHSBNT 8IFO UIBU
IBQQFOT JO )BTLFMM XF VTF FYQMJDJU EBUBUZQFT UP TJHOBM XIFO
PVS GVODUJPOT SFDFJWFE B DPNCJOBUJPO PG JOQVUT UIBU EPOƊU NBLF
TFOTF -BUFS XFƊMM TFF IPX UP EFGFOE BHBJOTU UIPTF BEWFSTF
JOQVUT BU UIF UJNF XF DPOTUSVDU PVS EBUBUZQFT CVU UIF Maybe
BOE Either EBUBUZQFT XF XJMM EFNPOTUSBUF IFSF BSF VTFE JO B
MPU PG )BTLFMM QSPHSBNT
5IJT DIBQUFS XJMM JODMVEF

Ƒ Nothing PS Just Maybe

Ƒ Either MFǒ PS SJHIU CVU OPU CPUI

Ƒ IJHIFSLJOEFEOFTT

Ƒ BOBNPSQIJTNT CVU OPU BOJNPSQIT

 )PX * MFBSOFE UP TUPQ XPSSZJOH


BOE MPWF /PUIJOH
-FUƊT DPOTJEFS UIF EFƶOJUJPO PG Maybe BHBJO

data Maybe a = Nothing | Just a


$)"15&3  4*(/"-*/( "%7&34*5: 

:PV EPOƊU OFFE UP EFƶOF UIJT ZPVSTFMG BT JUƊT JODMVEFE JO


UIF 1SFMVEF CZ EFGBVMU *UƊT BMTP B WFSZ DPNNPO EBUBUZQF JO
)BTLFMM CFDBVTF JU MFUT VT SFUVSO B EFGBVMU Nothing WBMVF XIFO
XF EPOƊU IBWF BOZ TFOTJCMF WBMVFT UP SFUVSO GPS PVS JOUFOEFE
UZQF B
*O UIF GPMMPXJOH JOUFOUJPOBMMZ TJNQMJTUJD GVODUJPO XF DPVME
EP TFWFSBM UIJOHT XJUI UIF PEE OVNCFST ƈ XF DPVME SFUVSO
UIFN VONPEJƶFE XF DPVME NPEJGZ UIFN JO TPNF XBZ EJG
GFSFOU GSPN UIF FWFOT XF DPVME SFUVSO B [FSP PS XF DPVME
XSJUF BO FYQMJDJU TJHOBM UIBU OPUIJOH IBQQFOFE CFDBVTF UIF
OVNCFS XBTOƊU FWFO

ifEvenAdd2 :: Integer -> Integer


ifEvenAdd2 n = if even n then n+2 else ???

8IBU DBO XF EP UP NBLF JU TBZ ƌIFZ UIJT OVNCFS XBTOƊU


FWFO TP * IBWF OPUIJOH GPS ZPV NZ GSJFOE ƍ 8FMM JOTUFBE PG
QSPNJTJOH BO Integer SFTVMU XF DBO SFUVSO Maybe Integer

ifEvenAdd2 :: Integer -> Maybe Integer


ifEvenAdd2 n = if even n then n+2 else Nothing

5IJT JTOƊU RVJUF DPNQMFUF PS DPSSFDU FJUIFS 8IJMF Nothing


IBT UIF UZQF Maybe a BOE B DBO CF BTTVNFE UP CF BOZ UZQF UIF
Maybe DPOTUSVDUPS DPVME DPOUBJO n+2 JT TUJMM PG UIF UZQF Integer
8F OFFE UP XSBQ UIBU WBMVF JO UIF PUIFS DPOTUSVDUPS Maybe
PƵFST Just )FSFƊT UIF FSSPS ZPVƊE HFU JG ZPV USJFE UP MPBE JU
$)"15&3  4*(/"-*/( "%7&34*5: 

<interactive>:9:75:
Couldn't match expected type ‘Maybe Integer’
with actual type ‘Integer’
In the first argument of ‘(+)’, namely ‘n’
In the expression: n + 2

"OE IFSFƊT IPX XF ƶY JU

ifEvenAdd2 :: Integer -> Maybe Integer


ifEvenAdd2 n = if even n then Just (n+2) else Nothing

8F IBE UP QBSFOUIFTJ[F n+2 CFDBVTF GVODUJPO BQQMJDBUJPO


CJOET UIF NPTU UJHIUMZ JO )BTLFMM IBT UIF IJHIFTU QSFDFEFODF

TP UIF DPNQJMFS PUIFSXJTF XPVMEƊWF QBSTFE JU BT (Just n) + 2
XIJDI JT XSPOH BOE UISPXT B UZQF FSSPS /PX PVS GVODUJPO
JT DPSSFDU BOE FYQMJDJU BCPVU UIF QPTTJCJMJUZ PG OPU HFUUJOH B
SFTVMU

4NBSU DPOTUSVDUPST GPS EBUBUZQFT


-FUƊT DPOTJEFS B Person UZQF XIJDI LFFQT USBDL PG UXP UIJOHT
UIFJS OBNF BOE UIFJS BHF 8FƊMM XSJUF UIJT VQ BT B TJNQMF QSPE
VDU UZQF

type Name = String


type Age = Integer

data Person = Person Name Age deriving Show


$)"15&3  4*(/"-*/( "%7&34*5: 

5IFSF BSF BMSFBEZ B GFX QSPCMFNT IFSF 0OF JT UIBU XF DPVME


DPOTUSVDU B Person XJUI BO FNQUZ String GPS B OBNF PS NBLF
B QFSTPO XIP JT OFHBUJWF ZFBST PME 5IJT JT OP QSPCMFN UP ƶY
XJUI Maybe UIPVHI

type Name = String


type Age = Integer

data Person = Person Name Age deriving Show

mkPerson :: Name -> Age -> Maybe Person


mkPerson name age
| name /= "" && age >= 0 = Just $ Person name age
| otherwise = Nothing

"OE JG ZPV MPBE UIJT JOUP ZPVS 3&1-

Prelude> mkPerson "John Browning" 160


Just (Person "John Browning" 160)

$PPM 8IBU IBQQFOT XIFO XF GFFE JU BEWFSTF EBUB

Prelude> mkPerson "" 160


Nothing
Prelude> mkPerson "blah" 0
Just (Person "blah" 0)
Prelude> mkPerson "blah" (-9001)
Nothing
$)"15&3  4*(/"-*/( "%7&34*5: 

mkPerson JT XIBU XF DBMM B TNBSU DPOTUSVDUPS *U BMMPXT VT UP


DPOTUSVDU WBMVFT PG B UZQF POMZ XIFO UIFZ NFFU DFSUBJO DSJUFSJB
TP UIBU XF LOPX XF IBWF B WBMJE WBMVF BOE SFUVSO BO FYQMJDJU
TJHOBM XIFO XF EP OPU
5IJT JT NVDI CFUUFS UIBO PVS PSJHJOBM CVU XIBU JG XF XBOU
UP LOPX JG JU XBT UIF OBNF BHF PS CPUI UIBU XBT CBE 8F NBZ
XBOU UP UFMM PVS VTFS TPNFUIJOH XBT XSPOH XJUI UIFJS JOQVU
'PSUVOBUFMZ XF IBWF B EBUBUZQF GPS UIBU

 #MFBUJOH FJUIFS


4P OPX XF XBOU B XBZ UP FYQSFTT XIZ XF EJEOƊU HFU B TVDDFTTGVM
SFTVMU CBDL GSPN PVS mkPerson DPOTUSVDUPS 5P IBOEMF UIBU
XFƊWF HPU UIF Either EBUBUZQF XIJDI JT EFƶOFE BT GPMMPXT JO UIF
1SFMVEF

data Either a b = Left a | Right b

8IBU XF XBOU JT B XBZ UP LOPX XIZ PVS JOQVUT XFSF JODPS


SFDU JG UIFZ XFSF JODPSSFDU 4P XFƊMM TUBSU CZ NBLJOH B TJNQMF
TVN UZQF UP FOVNFSBUF PVS GBJMVSF NPEFT

data PersonInvalid = NameEmpty


| AgeTooLow
deriving (Eq, Show)
$)"15&3  4*(/"-*/( "%7&34*5: 

#Z OPX ZPV LOPX XIZ XF EFSJWFE Show CVU JUƊT JNQPSUBOU


UIBU XF EFSJWF Eq CFDBVTF PUIFSXJTF XF DBOƊU FRVBMJUZ DIFDL UIF
DPOTUSVDUPST 1BUUFSO NBUDIJOH JT B DBTF FYQSFTTJPO XIFSF UIF
EBUB DPOTUSVDUPS JT UIF DPOEJUJPO $BTF FYQSFTTJPOT BOE QBUUFSO
NBUDIJOH XJMM XPSL XJUIPVU BO Eq JOTUBODF CVU HVBSET VTJOH
(==) XJMM OPU "T XFƊWF TIPXO ZPV QSFWJPVTMZ ZPV DBO XSJUF
ZPVS PXO Eq JOTUBODF GPS ZPVS EBUBUZQF JG ZPV XBOU B TQFDJƶD
CFIBWJPS CVU JUƊT VTVBMMZ OPU OFDFTTBSZ UP EP TP XF XJMM VTVBMMZ
EFSJWF UIF Eq JOTUBODF )FSFƊT UIF EJƵFSFODF EFNPOTUSBUFE JO
DPEF
$)"15&3  4*(/"-*/( "%7&34*5: 

module EqCaseGuard where

data PersonInvalid = NameEmpty


| AgeTooLow

-- Compiles fine without Eq


toString :: PersonInvalid -> String
toString NameEmpty = "NameEmpty"
toString AgeTooLow = "AgeTooLow"

instance Show PersonInvalid where


show = toString

-- This does not work without an Eq instance


blah :: PersonInvalid -> String
blah pi
| pi == NameEmpty = "NameEmpty"
| pi == AgeTooLow = "AgeTooLow"
| otherwise = "???"

*UƊT XPSUI DPOTJEFSJOH UIBU JG ZPV OFFEFE UP IBWF BO Eq JO


TUBODF UP QBUUFSO NBUDI IPX XPVME ZPV XSJUF UIF Eq JOTUBODFT
/FYU PVS DPOTUSVDUPS UZQF JT HPJOH UP DIBOHF UP

mkPerson :: Name -> Age -> Either PersonInvalid Person


$)"15&3  4*(/"-*/( "%7&34*5: 

5IJT TJHOJƶFT UIBU XFƊSF HPJOH UP HFU B Person WBMVF JG XF TVD


DFFE CVU B PersonInvalid JG JU GBJMT /PX XF OFFE UP DIBOHF PVS
MPHJD UP SFUVSO PersonInvalid WBMVFT JOTJEF B Left DPOTUSVDUPS
XIFO UIF EBUB JT JOWBMJE EJTDSJNJOBUJOH CZ FBDI DBTF BT XF HP

type Name = String


type Age = Integer

data Person = Person Name Age deriving Show

data PersonInvalid = NameEmpty


| AgeTooLow
deriving (Eq, Show)

mkPerson :: Name
-> Age
-> Either PersonInvalid Person
-- [1] [2] [3]
mkPerson name age
| name /= "" && age >= 0 = Right $ Person name age
-- [4]
| name == "" = Left NameEmpty
-- [5]
| otherwise = Left AgeTooLow

 0VS mkPerson UZQF UBLFT B Name BOE Age SFUVSOT BO Either


$)"15&3  4*(/"-*/( "%7&34*5: 

SFTVMU

 5IF Left SFTVMU PG UIF Either JT BO JOWBMJE QFSTPO XIFO


FJUIFS UIF OBNF PS BHF JT BO JOWBMJE JOQVU

 5IF Right SFTVMU JT B WBMJE QFSTPO

 5IF ƶSTU DBTF PG PVS mkPerson GVODUJPO UIFO NBUDIFT PO


UIF Right DPOTUSVDUPS PG UIF Either BOE SFUVSOT B Person
SFTVMU 8F DPVME IBWF XSJUUFO

name /= "" && age >= 0 = Right (Person name age)

JOTUFBE PG VTJOH UIF EPMMBS TJHO

 5IF OFYU UXP DBTFT NBUDI PO UIF Left DPOTUSVDUPS BOE


BMMPX VT UP UBJMPS PVS JOWBMJE SFTVMUT CBTFE PO UIF GBJMVSF
SFBTPOT 8F DBO QBUUFSO NBUDI PO Left CFDBVTF JUƊT POF PG
UIF DPOTUSVDUPST PG Either

8F VTF Left BT PVS JOWBMJE PS FSSPS DPOTUSVDUPS GPS B DPVQMF


PG SFBTPOT *U JT DPOWFOUJPOBM UP EP TP JO )BTLFMM CVU UIBU DPO
WFOUJPO DBNF BCPVU GPS B SFBTPO 5IF SFBTPO IBT UP EP XJUI UIF
PSEFSJOH PG UZQF BSHVNFOUT BOE BQQMJDBUJPO PG GVODUJPOT /PS
NBMMZ JU JT ZPVS FSSPS PS JOWBMJE SFTVMU UIBU JT HPJOH UP DBVTF B
TUPQ UP XIBUFWFS XPSL JT CFJOH EPOF CZ ZPVS QSPHSBN Functor
XJMM OPU NBQ PWFS UIF MFǒ UZQF BSHVNFOU CFDBVTF JU IBT CFFO
BQQMJFE BXBZ :PV NBZ SFNFNCFS Functor GSPN PVS JOUSPEVD
UJPO PG fmap CBDL JO UIF DIBQUFS BCPVU MJTUT EPOƊU XPSSZ B GVMM
$)"15&3  4*(/"-*/( "%7&34*5: 

FYQMBOBUJPO PG Functor JT DPNJOH TPPO 4JODF ZPV OPSNBMMZ


XBOU UP BQQMZ GVODUJPOT BOE NBQ PWFS UIF DBTF UIBU EPFTOƊU
TUPQ ZPVS QSPHSBN UIBU JT OPU UIF FSSPS DBTF
JU IBT CFDPNF
DPOWFOUJPO UIBU UIF Left PG Either JT VTFE GPS XIBUFWFS DBTF JT
HPJOH UP DBVTF UIF XPSL UP TUPQ
-FUƊT TFF XIBU JU MPPLT MJLF XIFO XF IBWF HPPE EBUB BMUIPVHI
%KBMJ JTOƊU SFBMMZ B QFSTPO

Prelude> :t mkPerson "Djali" 5


mkPerson "Djali" 5 :: Either PersonInvalid Person
Prelude> mkPerson "Djali" 5
Right (Person "Djali" 5)

5IFO XF DBO TFF XIBU UIJT EPFT GPS VT XIFO EFBMJOH XJUI
CBE EBUB

Prelude> mkPerson "" 10


Left NameEmpty
Prelude> mkPerson "Djali" (-1)
Left AgeTooLow
Prelude> mkPerson "" (-1)
Left NameEmpty

/PUJDF JO UIF MBTU FYBNQMF UIBU XIFO CPUI UIF OBNF BOE
UIF BHF BSF XSPOH XFƊSF KVTU HPJOH UP TFF UIF SFTVMU PG UIF ƶSTU
GBJMVSF DBTF OPU CPUI

%POƊU LOPX XIBU XF NFBO $IFDL UIF OBNF %KBMJ PO B TFBSDI FOHJOF
$)"15&3  4*(/"-*/( "%7&34*5: 

5IJT JT JNQFSGFDU JO POF SFTQFDU BT JU EPFTOƊU MFU VT FYQSFTT B


MJTU PG FSSPST 8F DBO ƶY UIJT UPP 0OF UIJOH UIBU XJMM DIBOHF JT
UIBU JOTUFBE PG WBMJEBUJOH BMM UIF EBUB GPS B Person BU PODF XFƊSF
HPJOH UP NBLF TFQBSBUF DIFDLJOH GVODUJPOT BOE UIFO DPNCJOF
UIF SFTVMUT 8FƊMM TFF NFBOT PG BCTUSBDUJOH QBUUFSOT MJLF UIJT
PVU MBUFS

type Name = String


type Age = Integer
type ValidatePerson a = Either [PersonInvalid] a
-- this type alias wasn't in our previous version
-- otherwise, these types are the same as above

data Person = Person Name Age deriving Show

data PersonInvalid = NameEmpty


| AgeTooLow
deriving (Eq, Show)

/PX XFƊMM XSJUF PVS DIFDLJOH GVODUJPOT "MUIPVHI NPSF


UIBO POF UIJOH DPVME IZQPUIFUJDBMMZ CF XSPOH XJUI UIF BHF
WBMVF XFƊMM LFFQ UIJT TJNQMF BOE POMZ DIFDL UP NBLF TVSF JUƊT B
QPTJUJWF Integer WBMVF
$)"15&3  4*(/"-*/( "%7&34*5: 

ageOkay :: Age -> Either [PersonInvalid] Age


ageOkay age = case age >= 0 of
True -> Right age
False -> Left [AgeTooLow]

nameOkay :: Name -> Either [PersonInvalid] Name


nameOkay name = case name /= "" of
True -> Right name
False -> Left [NameEmpty]

8F DBO OFTU UIF PersonInvalid TVN UZQF SJHIU JOUP UIF Left
QPTJUJPO PG Either KVTU BT XF TBX JO UIF QSFWJPVT DIBQUFS BM
UIPVHI XF XFSFOƊU VTJOH Either UIFSF CVU TJNJMBS UZQFT

" DPVQMF PG UIJOHT UP OPUF IFSF

Ƒ 5IF Name WBMVF XJMM POMZ SFUVSO UIJT JOWBMJE SFTVMU XIFO
JUƊT BO FNQUZ String

Ƒ 4JODF Name JT POMZ B String WBMVF JU DBO CF BOZ String XJUI


DIBSBDUFST JOTJEF JU TP ƌƍ JT TUJMM HPJOH UP SFUVSO BT B WBMJE
OBNF 5SZ JU

Ƒ *G ZPV USZ UP QVU BO Integer JO GPS UIF OBNF ZPV XPOƊU HFU
B Left SFTVMU ZPVƊMM HFU B UZQF FSSPS 5SZ JU 4JNJMBSMZ JG
ZPV USZ UP GFFE B TUSJOH WBMVF UP UIF ageOkay GVODUJPO
$)"15&3  4*(/"-*/( "%7&34*5: 

Ƒ 8FƊSF HPJOH UP SFUVSO B MJTU PG PersonInvalid SFTVMUT 5IBU


XJMM BMMPX VT UP SFUVSO CPUI NameEmpty BOE AgeTooLow JO DBTFT
XIFSF CPUI PG UIPTF BSF USVF

/PX UIBU PVS GVODUJPOT SFMZ PO Either UP WBMJEBUF UIBU UIF


BHF BOE OBNF WBMVFT BSF JOEFQFOEFOUMZ WBMJE XF DBO XSJUF B
mkPerson GVODUJPO UIBU XJMM VTF PVS UZQF BMJBT ValidatePerson

mkPerson :: Name -> Age -> ValidatePerson Person


-- [1] [2]

mkPerson name age =


mkPerson' (nameOkay name) (ageOkay age)
-- [3] [4] [5]

mkPerson' :: ValidatePerson Name


-> ValidatePerson Age
-> ValidatePerson Person
-- [6]

mkPerson' (Right nameOk) (Right ageOk) =


Right (Person nameOk ageOk)
mkPerson' (Left badName) (Left badAge) =
Left (badName ++ badAge)
mkPerson' (Left badName) _ = Left badName
mkPerson' _ (Left badAge) = Left badAge
$)"15&3  4*(/"-*/( "%7&34*5: 

 " UZQF BMJBT GPS Either [PersonInvalid] a

 5IJT JT UIF B BSHVNFOU UP ValidatePerson UZQF

 0VS NBJO GVODUJPO OPX SFMJFT PO B TJNJMBSMZOBNFE IFMQFS


GVODUJPO

 'JSTU BSHVNFOU UP UIJT GVODUJPO JT UIF SFTVMU PG UIF nameOkay


GVODUJPO

 4FDPOE BSHVNFOU JT UIF SFTVMU PG UIF ageOkay GVODUJPO

 5IF UZQF SFMJFT PO UIF TZOPOZN GPS Either

5IF SFTU PG PVS IFMQFS GVODUJPO mkPerson' BSF KVTU QMBJO PME
QBUUFSO NBUDIFT
/PX MFUƊT TFF XIBU XF HFU

Prelude> mkPerson "" (-1)


Left [NameEmpty,AgeTooLow]

"II UIBUƊT NPSF MJLF JU /PX XF DBO UFMM UIF VTFS XIBU XBT
JODPSSFDU JO POF HP XJUIPVU UIFN IBWJOH UP SPVOEUSJQ FBDI
NJTUBLF XJUI PVS QSPHSBN 8IBUƊT SFBMMZ HPJOH UP CBLF ZPVS
OPPEMF JT UIBU XFƊMM CF BCMF UP SFQMBDF mkPerson BOE mkPerson'
XJUI UIF GPMMPXJOH MBUFS JO UIJT CPPL
$)"15&3  4*(/"-*/( "%7&34*5: 

mkPerson :: Name
-> Age
-> Validation [PersonInvalid] Person
mkPerson name age =
liftA2 Person (nameOkay name) (ageOkay age)

 ,JOET B UIPVTBOE TUBST JO ZPVS


UZQFT
,JOET BSF UZQFT POF MFWFM VQ 5IFZ BSF VTFE UP EFTDSJCF UIF
UZQFT PG UZQF DPOTUSVDUPST 0OF OPUFXPSUIZ GFBUVSF PG )BTLFMM
JT UIBU JU IBT IJHIFSLJOEFE UZQFT )FSF UIF UFSN ƉIJHIFSLJOEFEƊ
EFSJWFT GSPN IJHIFSPSEFS GVODUJPOT GVODUJPOT UIBU UBLF NPSF
GVODUJPOT BT BSHVNFOUT 5ZQF DPOTUSVDUPST UIBU JT IJHIFS
LJOEFE UZQFT
BSF UZQFT UIBU UBLF NPSF UZQFT BT BSHVNFOUT 5IF
)BTLFMM 3FQPSU VTFT UIF UFSN UZQF DPOTUBOU UP SFGFS UP UZQFT UIBU
UBLF OP BSHVNFOUT BOE BSF BMSFBEZ UZQFT *O UIF 3FQPSU UZQF
DPOTUSVDUPS JT VTFE UP SFGFS UP UZQFT XIJDI NVTU IBWF BSHVNFOUT
BQQMJFE UP CFDPNF B UZQF
"T XF EJTDVTTFE JO UIF MBTU DIBQUFS UIFTF BSF FYBNQMFT PG
UZQF DPOTUBOUT

Prelude> :kind Int


Int :: *
Prelude> :k Bool
Bool :: *
$)"15&3  4*(/"-*/( "%7&34*5: 

Prelude> :k Char
Char :: *

5IF :: TZOUBY VTVBMMZ NFBOT ƌIBT UZQF PG ƍ CVU JU JT VTFE GPS


LJOE TJHOBUVSFT BT XFMM BT UZQF TJHOBUVSFT
5IF GPMMPXJOH JT BO FYBNQMF PG B UZQF UIBU IBT B UZQF DPO
TUSVDUPS SBUIFS UIBO B UZQF DPOTUBOU

data Example a = Blah | RoofGoats | Woot a

Example JT B UZQF DPOTUSVDUPS SBUIFS UIBO B DPOTUBOU CFDBVTF


JU UBLFT B UZQF BSHVNFOU B XIJDI JT VTFE XJUI UIF Woot EBUB
DPOTUSVDUPS *O ()$J XF DBO RVFSZ LJOET XJUI :k

Prelude> data Example a = Blah | RoofGoats | Woot a


Prelude> :k Example
Example :: * -> *

Example IBT POF BSHVNFOU TP JU NVTU CF BQQMJFE UP POF UZQF


JO PSEFS UP CFDPNF B DPODSFUF UZQF SFQSFTFOUFE CZ B TJOHMF *
5IF UXPUVQMF UBLFT UXP BSHVNFOUT TP JU NVTU CF BQQMJFE UP
UXP UZQFT UP CFDPNF B DPODSFUF UZQF

Prelude> :k (,)
(,) :: * -> * -> *

Prelude> :k (Int, Int)


(Int, Int) :: *
$)"15&3  4*(/"-*/( "%7&34*5: 

5IF Maybe BOE Either EBUBUZQFT XFƊWF KVTU SFWJFXFE BMTP IBWF
UZQF DPOTUSVDUPST SBUIFS UIBO DPOTUBOUT 5IFZ IBWF UP CF BQ
QMJFE UP BO BSHVNFOU CFGPSF UIFZ CFDPNF DPODSFUF UZQFT +VTU
BT XF TBX XJUI UIF FƵFDU PG DVSSZJOH JO UZQF TJHOBUVSFT BQQMZ
JOH Maybe UP BO a UZQF DPOTUSVDUPS SFMJFWFT VT PG POF BSSPX BOE
NBLFT JU B LJOE TUBS

Prelude> :k Maybe
Maybe :: * -> *
Prelude> :k Maybe Int
Maybe Int :: *

0O UIF PUIFS IBOE Either IBT UP CF BQQMJFE UP UXP BSHV


NFOUT BO B BOE B C TP UIF LJOE PG Either JT TUBS UP TUBS UP TUBS

Prelude> :k Either
Either :: * -> * -> *

"OE BHBJO XF DBO RVFSZ UIF FƵFDUT PG BQQMZJOH JU UP BSHV


NFOUT

Prelude> :k Either Int


Either Int :: * -> *
Prelude> :k Either Int String
Either Int String :: *

"T XFƊWF TBJE UIF LJOE * SFQSFTFOUT B DPODSFUF UZQF 5IFSF


JT OPUIJOH MFǒ BXBJUJOH BQQMJDBUJPO
$)"15&3  4*(/"-*/( "%7&34*5: 

-JǒFE BOE VOMJǒFE UZQFT 5P CF QSFDJTF LJOE * JT UIF LJOE PG


BMM TUBOEBSE MJǒFE UZQFT XIJMF UZQFT UIBU IBWF UIF LJOE # BSF
VOMJǒFE " MJǒFE UZQF XIJDI JODMVEFT BOZ EBUBUZQF ZPV DPVME
EFƶOF ZPVSTFMG JT BOZ UIBU DBO CF JOIBCJUFE CZ CPUUPN -JǒFE
UZQFT BSF SFQSFTFOUFE CZ B QPJOUFS BOE JODMVEF NPTU PG UIF
EBUBUZQFT XFƊWF TFFO BOE NPTU UIBU ZPVƊSF MJLFMZ UP FODPVOUFS
BOE VTF 6OMJǒFE UZQFT BSF BOZ UZQF XIJDI DBOOPU CF JOIBCJUFE
CZ CPUUPN 5ZQFT PG LJOE # BSF PǒFO OBUJWF NBDIJOF UZQFT
BOE SBX QPJOUFST /FXUZQFT BSF B TQFDJBM DBTF JO UIBU UIFZ BSF
LJOE * CVU BSF VOMJǒFE CFDBVTF UIFJS SFQSFTFOUBUJPO JT JEFOUJDBM
UP UIBU PG UIF UZQF UIFZ DPOUBJO TP UIF OFXUZQF JUTFMG JT OPU
DSFBUJOH BOZ OFX QPJOUFS CFZPOE UIBU PG UIF UZQF JU DPOUBJOT
5IBU GBDU NFBOT UIBU UIF OFXUZQF JUTFMG DBOOPU CF JOIBCJUFE
CZ CPUUPN POMZ UIF UIJOH JU DPOUBJOT DBO CF TP OFXUZQFT BSF
VOMJǒFE 5IF EFGBVMU LJOE PG DPODSFUF GVMMZBQQMJFE EBUBUZQFT
JO ()$ JT LJOE *
/PX XIBU IBQQFOT JG XF MFU PVS UZQF DPOTUSVDUPS UBLF BO
BSHVNFOU

Prelude> newtype Identity a = Identity a


Prelude> :k Identity
Identity :: * -> *

"T XF EJTDVTTFE JO UIF QSFWJPVT DIBQUFS UIF BSSPX JO UIF


LJOE TJHOBUVSF MJLF UIF GVODUJPO BSSPX JO UZQF TJHOBUVSFT TJH
OBMT B OFFE GPS BQQMJDBUJPO *O UIJT DBTF XF DPOTUSVDU UIF UZQF
CZ BQQMZJOH JU UP BOPUIFS UZQF
$)"15&3  4*(/"-*/( "%7&34*5: 

-FUƊT DPOTJEFS UIF DBTF PG Maybe XIJDI JT EFƶOFE BT GPMMPXT

data Maybe a = Nothing | Just a

5IF UZQF Maybe JT B UZQF DPOTUSVDUPS CFDBVTF JU UBLFT POF


BSHVNFOU CFGPSF JU CFDPNFT B ƌSFBMƍ UZQF

Prelude> :k Maybe
Maybe :: * -> *

Prelude> :k Maybe Int


Maybe Int :: *
Prelude> :k Maybe Bool
Maybe Bool :: *

Prelude> :k Int
Int :: *
Prelude> :k Bool
Bool :: *

8IFSFBT UIF GPMMPXJOH XJMM OPU XPSL CFDBVTF UIF LJOET


EPOƊU NBUDI VQ

Prelude> :k Maybe Maybe

Expecting one more argument to ‘Maybe’


$)"15&3  4*(/"-*/( "%7&34*5: 

The first argument of ‘Maybe’ should have kind ‘*’,


but ‘Maybe’ has kind ‘* -> *’
In a type in a GHCi command: Maybe Maybe

Maybe FYQFDUT B TJOHMF UZQF BSHVNFOU PG LJOE * XIJDI Maybe


JT OPU
*G XF HJWF Maybe B UZQF BSHVNFOU UIBU JT LJOE * JU BMTP CF
DPNFT LJOE * TP UIFO JU DBO JO GBDU CF BO BSHVNFOU UP BOPUIFS
Maybe

Prelude> :k Maybe Char


Maybe Char :: *

Prelude> :k Maybe (Maybe Char)


Maybe (Maybe Char) :: *

0VS Example EBUBUZQF GSPN FBSMJFS BMTP XPOƊU XPSL BT BO


BSHVNFOU GPS Maybe CZ JUTFMG

Prelude> data Example a = Blah | RoofGoats | Woot a

Prelude> :k Maybe Example

Expecting one more argument to ‘Example’


The first argument of ‘Maybe’ should have kind ‘*’,
$)"15&3  4*(/"-*/( "%7&34*5: 

but ‘Example’ has kind ‘* -> *’


In a type in a GHCi command: Maybe Example

)PXFWFS JG XF BQQMZ UIF Example UZQF DPOTUSVDUPS XF DBO


NBLF JU XPSL BOE DSFBUF B WBMVF PG UIBU UZQF

Prelude> :k Maybe (Example Int)


Maybe (Example Int) :: *
Prelude> :t Just (Woot n)
Just (Woot n) :: Maybe (Example Int)

/PUF UIBU UIF MJTU UZQF DPOTUSVDUPS [] JT BMTP LJOE * -> * BOE
PUIFSXJTF VOFYDFQUJPOBM TBWF GPS TPNF OJDF MPPLJOH CSBDLFU
TZOUBY UIBU MFUT ZPV UZQF [a] BOE [Int] JOTUFBE PG [] a BOE []
Int

Prelude> :k []
[] :: * -> *

Prelude :k [] Int
[] Int :: *

Prelude> :k [Int]
[Int] :: *

4P XF DBOƊU IBWF KVTU B Maybe [] GPS UIF TBNF SFBTPO XF


DPVMEOƊU IBWF KVTU B Maybe Maybe CVU XF DBO IBWF B Maybe [Bool]
$)"15&3  4*(/"-*/( "%7&34*5: 

Prelude> :k Maybe []

Expecting one more argument to ‘[]’


The first argument of ‘Maybe’ should have kind ‘*’,
but ‘[]’ has kind ‘* -> *’
In a type in a GHCi command: Maybe []

Prelude> :k Maybe [Bool]


Maybe [Bool] :: *

*G ZPV SFDBMM POF PG UIF ƶSTU UJNFT XF VTFE Maybe JO UIF CPPL
XBT UP XSJUF B TBGF WFSTJPO PG B tail GVODUJPO CBDL JO UIF DIBQUFS
PO -JTUT

safeTail :: [a] -> Maybe [a]


safeTail [] = Nothing
safeTail (x:[]) = Nothing
safeTail (_:xs) = Just xs

"T TPPO BT XF BQQMZ UIJT UP B WBMVF UIF QPMZNPSQIJD UZQF


WBSJBCMFT CFDPNF DPOTUSBJOFE PS DPODSFUF UZQFT

*Main> safeTail "julie"


Just "ulie"
*Main> :t safeTail "julie"
safeTail "julie" :: Maybe [Char]
$)"15&3  4*(/"-*/( "%7&34*5: 

*Main> safeTail [1..10]


Just [2,3,4,5,6,7,8,9,10]
*Main> :t safeTail [1..10]
safeTail [1..10] :: (Num a, Enum a) => Maybe [a]

*Main> :t safeTail [1..10 :: Int]


safeTail [1..10 :: Int] :: Maybe [Int]

8F DBO FYQBOE PO UZQF DPOTUSVDUPST UIBU UBLF B TJOHMF BSHV


NFOU BOE TFF IPX UIF LJOE DIBOHFT BT XF HP

Prelude> data Trivial = Trivial


Prelude> :k Trivial
Trivial :: *

Prelude> data Unary a = Unary a


Prelude> :k Unary
Unary :: * -> *

Prelude> data TwoArgs a b = TwoArgs a b


Prelude> :k TwoArgs
TwoArgs :: * -> * -> *

Prelude> data ThreeArgs a b c = ThreeArgs a b c


Prelude> :k ThreeArgs
ThreeArgs :: * -> * -> * -> *
$)"15&3  4*(/"-*/( "%7&34*5: 

*U NBZ OPU CF DMFBS XIZ UIJT JT VTFGVM UP LOPX SJHIU OPX


PUIFS UIBO IFMQJOH UP VOEFSTUBOE XIFO ZPVS UZQF FSSPST BSF
DBVTFE CZ UIJOHT OPU CFJOH GVMMZ BQQMJFE 5IF JNQMJDBUJPOT PG
IJHIFSLJOEFEOFTT XJMM CF DMFBSFS JO B MBUFS DIBQUFS

%BUB DPOTUSVDUPST BSF GVODUJPOT


*O UIF QSFWJPVT DIBQUFS XF OPUFE UIF EJƵFSFODF CFUXFFO EBUB
DPOTUBOUT BOE EBUB DPOTUSVDUPST BOE OPUFE UIBU EBUB DPOTUSVD
UPST UIBU IBWFOƊU CFFO GVMMZ BQQMJFE IBWF GVODUJPO BSSPXT JO
UIFN 0ODF ZPV BQQMZ UIFN UP UIFJS BSHVNFOUT UIFZ SFUVSO B
WBMVF PG UIF BQQSPQSJBUF UZQF *O PUIFS XPSET EBUB DPOTUSVD
UPST SFBMMZ BSF GVODUJPOT "T JU IBQQFOT UIFZ CFIBWF KVTU MJLF
)BTLFMM GVODUJPOT JO UIBU UIFZ BSF DVSSJFE BT XFMM
'JSTU MFUƊT PCTFSWF UIBU OVMMBSZ EBUB DPOTUSVDUPST UIBU BSF
SFBMMZ KVTU WBMVFT BOE UBLF OP BSHVNFOUT BSF OPU MJLF GVODUJPOT

Prelude> data Trivial = Trivial deriving Show


Prelude> Trivial 1

Couldn't match expected type ‘Integer -> t’


with actual type ‘Trivial’
(... etc ...)

)PXFWFS EBUB DPOTUSVDUPST UIBU UBLF BSHVNFOUT EP CFIBWF


MJLF GVODUJPOT
$)"15&3  4*(/"-*/( "%7&34*5: 

Prelude> data UnaryC = UnaryC Int deriving Show


Prelude> :t UnaryC
UnaryC :: Int -> UnaryC
Prelude> UnaryC 10
UnaryC 10
Prelude> :t UnaryC 10
UnaryC 10 :: UnaryC

"OE KVTU MJLF GVODUJPOT UIFJS BSHVNFOUT BSF UZQFDIFDLFE


BHBJOTU UIF TQFDJƶDBUJPO JO UIF UZQF

Prelude> UnaryC "blah"

Couldn't match expected type ‘Int’


with actual type ‘[Char]’

*G XF XBOUFE B VOBSZ EBUB DPOTUSVDUPS XIJDI DPVME DPOUBJO


BOZ UZQF XF XPVME QBSBNFUFSJ[F UIF UZQF MJLF TP

Prelude> data Unary a = Unary a deriving Show


Prelude> :t Unary
Unary :: a -> Unary a
Prelude> :t Unary 10
Unary 10 :: Num a => Unary a
Prelude> :t Unary "blah"
Unary "blah" :: Unary [Char]
$)"15&3  4*(/"-*/( "%7&34*5: 

"OE BHBJO UIJT XPSLT KVTU MJLF B GVODUJPO FYDFQU UIF UZQF
PG UIF BSHVNFOU DBO CF XIBUFWFS XF XBOU
/PUF UIBU JG XF XBOU UP VTF B EFSJWFE ()$ HFOFSBUFE
4IPX
JOTUBODF GPS Unary JU IBT UP CF BCMF UP BMTP TIPX UIF DPOUFOUT
UIF UZQF B WBMVF DPOUBJOFE CZ 6OBSZƊT EBUB DPOTUSVDUPS

Prelude> :info Unary


data Unary a = Unary a
instance Show a => Show (Unary a)

*G XF USZ UP VTF B UZQF GPS B UIBU EPFT OPU IBWF B Show JOTUBODF
JU XPOƊU DBVTF B QSPCMFN VOUJM XF USZ UP TIPX UIF WBMVF

-- no problem with using the id function


Prelude> :t (Unary id)
(Unary id) :: Unary (t -> t)

-- but id doesn't have a Show instance


Prelude> show (Unary id)

<interactive>:53:1:
No instance for (Show (t0 -> t0))
...

5IF POMZ XBZ UP BWPJE UIJT XPVME CF UP XSJUF BO JOTUBODF UIBU


EJE OPU TIPX UIF WBMVF DPOUBJOFE JO UIF Unary EBUB DPOTUSVDUPS
CVU UIBU XPVME CF TPNFXIBU VOVTVBM
$)"15&3  4*(/"-*/( "%7&34*5: 

"OPUIFS UIJOH UP LFFQ JO NJOE JT UIBU ZPV DBOƊU PSEJOBSJMZ


IJEF QPMZNPSQIJD UZQFT GSPN ZPVS UZQF DPOTUSVDUPS TP UIF
GPMMPXJOH JT JOWBMJE

Prelude> data Unary = Unary a deriving Show

Not in scope: type variable ‘a’

*O PSEFS GPS UIF UZQF WBSJBCMF B UP CF JO TDPQF XF VTVBMMZ


OFFE UP JOUSPEVDF JU XJUI PVS UZQF DPOTUSVDUPS 5IFSF BSF XBZT
BSPVOE UIJT CVU UIFZƊSF SBSFMZ OFDFTTBSZ PS B HPPE JEFB BOE
OPU SFMFWBOU UP UIF CFHJOOJOH )BTLFMMFS
)FSFƊT BO FYBNQMF VTJOH fmap BOE UIF Just EBUB DPOTUSVDUPS
GSPN Maybe UP EFNPOTUSBUF IPX +VTU JT BMTP MJLF B GVODUJPO

Prelude> fmap Just [1, 2, 3]


[Just 1,Just 2,Just 3]

5IF TJHOJƶDBODF BOE VUJMJUZ PG UIJT NBZ OPU CF JNNFEJBUFMZ


PCWJPVT CVU XJMM CF NPSF DMFBS JO MBUFS DIBQUFST

 $IBQUFS &YFSDJTFT


%FUFSNJOF UIF LJOET
 (JWFO

id :: a -> a
$)"15&3  4*(/"-*/( "%7&34*5: 

8IBU JT UIF LJOE PG B

 r :: a -> f a

8IBU BSF UIF LJOET PG B BOE G

4USJOH QSPDFTTJOH
#FDBVTF UIJT JT UIF LJOE PG UIJOH MJOHVJTUT BIFN FOKPZ EPJOH JO
UIFJS TQBSF UJNF

 8SJUF B SFDVSTJWF GVODUJPO OBNFE replaceThe XIJDI UBLFT B


UFYUTUSJOH CSFBLT JU JOUP XPSET BOE SFQMBDFT FBDI JOTUBODF
PG ƌUIFƍ XJUI ƌBƍ *UƊT JOUFOEFE POMZ UP SFQMBDF FYBDUMZ
UIF XPSE ƌUIFƍ notThe JT B TVHHFTUFE IFMQFS GVODUJPO GPS
BDDPNQMJTIJOH UIJT

-- example GHCi session above the functions

-- >>> notThe "the"


-- Nothing
-- >>> notThe "blahtheblah"
-- Just "blahtheblah"
-- >>> notThe "woot"
-- Just "woot"
notThe :: String -> Maybe String
notThe = undefined
$)"15&3  4*(/"-*/( "%7&34*5: 

-- >>> replaceThe "the cow loves us"


-- "a cow loves us"
replaceThe :: String -> String
replaceThe = undefined

 8SJUF B SFDVSTJWF GVODUJPO UIBU UBLFT B UFYUTUSJOH CSFBLT


JU JOUP XPSET BOE DPVOUT UIF OVNCFS PG JOTUBODFT PG ƍUIFƍ
GPMMPXFE CZ B WPXFMJOJUJBM XPSE

-- >>> countTheBeforeVowel "the cow"


-- 0
-- >>> countTheBeforeVowel "the evil cow"
-- 1
countTheBeforeVowel :: String -> Integer
countTheBeforeVowel = undefined

 3FUVSO UIF OVNCFS PG MFUUFST UIBU BSF WPXFMT JO B XPSE


)JOU JUƊT IFMQGVM UP CSFBL UIJT JOUP TUFQT "EE BOZ IFMQFS
GVODUJPOT OFDFTTBSZ UP BDIJFWF ZPVS PCKFDUJWFT

B
5FTU GPS WPXFMIPPE
C
3FUVSO UIF WPXFMT PG B TUSJOH
D
$PVOU UIF OVNCFS PG FMFNFOUT SFUVSOFE
$)"15&3  4*(/"-*/( "%7&34*5: 

-- >>> countVowels "the cow"


-- 2
-- >>> countVowels "Mikolajczak"
-- 4
countVowels :: String -> Integer
countVowels = undefined

7BMJEBUF UIF XPSE


6TF UIF Maybe UZQF UP XSJUF B GVODUJPO UIBU DPVOUT UIF OVNCFS
PG WPXFMT JO B TUSJOH BOE UIF OVNCFS PG DPOTPOBOUT *G UIF
OVNCFS PG WPXFMT FYDFFET UIF OVNCFS PG DPOTPOBOUT UIF
GVODUJPO SFUVSOT Nothing *O NBOZ IVNBO MBOHVBHFT WPXFMT
SBSFMZ FYDFFE UIF OVNCFS PG DPOTPOBOUT TP XIFO UIFZ EP JU
JOEJDBUFT UIF JOQVU JTOƊU B SFBM XPSE UIBU JT B WBMJE JOQVU UP
ZPVS EBUBTFU


newtype Word' =
Word' String
deriving (Eq, Show)

vowels = "aeiou"

mkWord :: String -> Maybe Word'


mkWord = undefined
$)"15&3  4*(/"-*/( "%7&34*5: 

*UƊT POMZ /BUVSBM


:PVƊMM CF QSFTFOUFE XJUI B EBUBUZQF UP SFQSFTFOU UIF OBUVSBM
OVNCFST 5IF POMZ WBMVFT SFQSFTFOUBCMF XJUI UIF OBUVSBMT
BSF XIPMF OVNCFST GSPN [FSP UP JOƶOJUZ :PVS UBTL XJMM CF
UP JNQMFNFOU GVODUJPOT UP DPOWFSU NaturalT UP IntegerT BOE
IntegerT UP NaturalT 5IF DPOWFSTJPO GSPN NaturalT UP IntegerT
XPOƊU SFUVSO Maybe CFDBVTF Integer JT B TUSJDU TVQFSTFU PG Natural
"OZ Natural DBO CF SFQSFTFOUFE CZ BO Integer CVU UIF TBNF JT
OPU USVF PG BOZ Integer /FHBUJWF OVNCFST BSF OPU WBMJE OBUVSBM
OVNCFST
$)"15&3  4*(/"-*/( "%7&34*5: 

-- As natural as any competitive bodybuilder


data Nat =
Zero
| Succ Nat
deriving (Eq, Show)

-- >>> natToInteger Zero


-- 0
-- >>> natToInteger (Succ Zero)
-- 1
-- >>> natToInteger (Succ (Succ Zero))
-- 2
natToInteger :: Nat -> Integer
natToInteger = undefined

-- >>> integerToNat 0
-- Just Zero
-- >>> integerToNat 1
-- Just (Succ Zero)
-- >>> integerToNat 2
-- Just (Succ (Succ Zero))
-- >>> integerToNat (-1)
-- Nothing
integerToNat :: Integer -> Maybe Nat
integerToNat = undefined
$)"15&3  4*(/"-*/( "%7&34*5: 

4NBMM MJCSBSZ GPS .BZCF


8SJUF UIF GPMMPXJOH GVODUJPOT 5IJT NBZ UBLF TPNF UJNF

 4JNQMF CPPMFBO DIFDLT GPS Maybe WBMVFT

-- >>> isJust (Just 1)


-- True
-- >>> isJust Nothing
-- False
isJust :: Maybe a -> Bool

-- >>> isNothing (Just 1)


-- False
-- >>> isNothing Nothing
-- True
isNothing :: Maybe a -> Bool

 5IF GPMMPXJOH JT UIF Maybe DBUBNPSQIJTN :PV DBO UVSO B


Maybe WBMVF JOUP BOZUIJOH FMTF XJUI UIJT

-- >>> mayybee 0 (+1) Nothing


-- 0
-- >>> mayybee 0 (+1) (Just 1)
-- 2
mayybee :: b -> (a -> b) -> Maybe a -> b
$)"15&3  4*(/"-*/( "%7&34*5: 

 *O DBTF ZPV KVTU XBOU UP QSPWJEF B GBMMCBDL WBMVF

-- >>> fromMaybe 0 Nothing


-- 0
-- >>> fromMaybe 0 (Just 1)
-- 1
fromMaybe :: a -> Maybe a -> a

-- Try writing it in terms of the maybe catamorphism

 $POWFSUJOH CFUXFFO List BOE Maybe

-- >>> listToMaybe [1, 2, 3]


-- Just 1
-- >>> listToMaybe []
-- Nothing
listToMaybe :: [a] -> Maybe a

-- >>> maybeToList (Just 1)


-- [1]
-- >>> maybeToList Nothing
-- []
maybeToList :: Maybe a -> [a]

 'PS XIFO XF KVTU XBOU UP ESPQ UIF Nothing WBMVFT GSPN


PVS MJTU
$)"15&3  4*(/"-*/( "%7&34*5: 

-- >>> catMaybes [Just 1, Nothing, Just 2]


-- [1, 2]
-- >>> catMaybes [Nothing, Nothing, Nothing]
-- []
catMaybes :: [Maybe a] -> [a]

 :PVƊMM TFF UIJT DBMMFE ƌTFRVFODFƍ MBUFS

-- >>> flipMaybe [Just 1, Just 2, Just 3]


-- Just [1, 2, 3]
-- >>> flipMaybe [Just 1, Nothing, Just 3]
-- Nothing
flipMaybe :: [Maybe a] -> Maybe [a]

4NBMM MJCSBSZ GPS &JUIFS


8SJUF FBDI PG UIF GPMMPXJOH GVODUJPOT *G NPSF UIBO POF QPTTJ
CMF VOJRVF GVODUJPO FYJTUT GPS UIF UZQF VTF DPNNPO TFOTF UP
EFUFSNJOF XIBU JU TIPVME EP

 5SZ UP FWFOUVBMMZ BSSJWF BU B TPMVUJPO UIBU VTFT foldr FWFO


JG FBSMJFS WFSTJPOT EPOƊU VTF foldr

lefts' :: [Either a b] -> [a]

 4BNF BT UIF MBTU POF 6TF foldr FWFOUVBMMZ

rights' :: [Either a b] -> [b]


$)"15&3  4*(/"-*/( "%7&34*5: 

 partitionEithers' :: [Either a b] -> ([a], [b])

 eitherMaybe' :: (b -> c) -> Either a b -> Maybe c

 5IJT JT B HFOFSBM DBUBNPSQIJTN GPS Either WBMVFT

either' :: (a -> c) -> (b -> c) -> Either a b -> c

 4BNF BT CFGPSF CVU VTF UIF either' GVODUJPO ZPV KVTU


XSPUF

eitherMaybe'' :: (b -> c) -> Either a b -> Maybe c

.PTU PG UIF GVODUJPOT ZPV KVTU TBX BSF JO UIF 1SFMVEF Data.Maybe
PS Data.Either CVU ZPV TIPVME TUSJWF UP XSJUF UIFN ZPVSTFMG
XJUIPVU MPPLJOH BU FYJTUJOH JNQMFNFOUBUJPOT :PV XJMM EFQSJWF
ZPVSTFMG JG ZPV DIFBU

6OGPMET
8IJMF UIF JEFB PG DBUBNPSQIJTNT JT TUJMM SFMBUJWFMZ GSFTI JO PVS
NJOET MFUƊT UVSO PVS BUUFOUJPO UP UIFJS EVBM BOBNPSQIJTNT *G
GPMET PS DBUBNPSQIJTNT MFU VT CSFBL EBUB TUSVDUVSFT EPXO
UIFO VOGPMET MFU VT CVJME UIFN VQ 5IFSF BSF KVTU BT XJUI GPMET
B GFX EJƵFSFOU XBZT UP VOGPME B EBUB TUSVDUVSF 8F DBO VTF
UIFN UP DSFBUF ƶOJUF BOE JOƶOJUF EBUB TUSVDUVSFT BMJLF

-- iterate is like a very limited


$)"15&3  4*(/"-*/( "%7&34*5: 

-- unfold that never ends


Prelude> :t iterate
iterate :: (a -> a) -> a -> [a]

-- because it never ends, we must use


-- take to get a finite list
Prelude> take 10 $ iterate (+1) 0
[0,1,2,3,4,5,6,7,8,9]

-- unfoldr is more general, the full monty as it were


Prelude> :t unfoldr
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]

-- Using unfoldr to do the same thing as iterate


Prelude> take 10 $ unfoldr (\b -> Just (b, b+1)) 0
[0,1,2,3,4,5,6,7,8,9]

8IZ CPUIFS
8F CPUIFS XJUI UIJT GPS UIF TBNF SFBTPO XF BCTUSBDUFE EJSFDU
SFDVSTJPO JOUP GPMET TVDI BT XJUI sum product BOE concat
$)"15&3  4*(/"-*/( "%7&34*5: 

import Data.List

mehSum :: Num a => [a] -> a


mehSum xs = go 0 xs
where go :: Num a => a -> [a] -> a
go n [] = n
go n (x:xs) = (go (n+x) xs)

niceSum :: Num a => [a] -> a


niceSum = foldl' (+) 0

mehProduct :: Num a => [a] -> a


mehProduct xs = go 1 xs
where go :: Num a => a -> [a] -> a
go n [] = n
go n (x:xs) = (go (n*x) xs)

niceProduct :: Num a => [a] -> a


niceProduct = foldl' (*) 1

3FNFNCFS UIF SFEVOEBOU TUSVDUVSF XIFO XF MPPLFE BU


GPMET
$)"15&3  4*(/"-*/( "%7&34*5: 

mehConcat :: [[a]] -> [a]


mehConcat xs = go [] xs
where go :: [a] -> [[a]] -> [a]
go xs' [] = xs'
go xs' (x:xs) = (go (xs' ++ x) xs)

niceConcat :: [[a]] -> [a]


niceConcat = foldr (++) []

:PVS FZFT NBZ CF TQPVUJOH HPVUT PG CMPPE CVU ZPV NBZ


BMTP TFF UIBU UIJT TBNF QSJODJQMF PG BCTUSBDUJOH PVU DPNNPO
QBUUFSOT BOE HJWJOH UIFN OBNFT BQQMJFT BT XFMM UP VOGPMET BT
JU EPFT UP GPMET

8SJUF ZPVS PXO JUFSBUF BOE VOGPMES


 8SJUF UIF GVODUJPO myIterate VTJOH EJSFDU SFDVSTJPO $PN
QBSF UIF CFIBWJPS XJUI UIF CVJMUJO iterate UP HBVHF DPS
SFDUOFTT %P OPU MPPL BU UIF TPVSDF PS BOZ FYBNQMFT PG
iterate TP UIBU ZPV BSF GPSDFE UP EP UIJT ZPVSTFMG

myIterate :: (a -> a) -> a -> [a]


myIterate = undefined

 8SJUF UIF GVODUJPO myUnfoldr VTJOH EJSFDU SFDVSTJPO $PN


QBSF XJUI UIF CVJMUJO unfoldr UP DIFDL ZPVS JNQMFNFOUB
$)"15&3  4*(/"-*/( "%7&34*5: 

UJPO "HBJO EPOƊU MPPL BU JNQMFNFOUBUJPOT PG unfoldr TP


UIBU ZPV ƶHVSF JU PVU ZPVSTFMG

myUnfoldr :: (b -> Maybe (a, b)) -> b -> [a]


myUnfoldr = undefined

 3FXSJUF myIterate JOUP betterIterate VTJOH myUnfoldr "


IJOU ƈ XF VTFE unfoldr UP QSPEVDF UIF TBNF SFTVMUT BT
iterate FBSMJFS %P UIJT XJUI EJƵFSFOU GVODUJPOT BOE TFF JG
ZPV DBO BCTUSBDU UIF TUSVDUVSF PVU

-- It helps to have the types in front of you


-- myUnfoldr :: (b -> Maybe (a, b)) -> b -> [a]

betterIterate :: (a -> a) -> a -> [a]


betterIterate f x = myUnfoldr ...?

3FNFNCFS ZPVS betterIterate TIPVME IBWF UIF TBNF SF


TVMUT BT iterate

Prelude> take 10 $ iterate (+1) 0


[0,1,2,3,4,5,6,7,8,9]

Prelude> take 10 $ betterIterate (+1) 0


[0,1,2,3,4,5,6,7,8,9]
$)"15&3  4*(/"-*/( "%7&34*5: 

'JOBMMZ TPNFUIJOH PUIFS UIBO B MJTU


(JWFO UIF BinaryTree GSPN MBTU DIBQUFS DPNQMFUF UIF GPMMPXJOH
FYFSDJTFT )FSFƊT UIBU EBUBUZQF BHBJO

data BinaryTree a =
Leaf
| Node (BinaryTree a) a (BinaryTree a)
deriving (Eq, Ord, Show)

 8SJUF unfold GPS BinaryTree

unfold :: (a -> Maybe (a,b,a)) -> a -> BinaryTree b


unfold = undefined

 .BLF B USFF CVJMEFS


6TJOH UIF unfold GVODUJPO ZPVƊWF KVTU NBEF GPS BinaryTree
XSJUF UIF GPMMPXJOH GVODUJPO

treeBuild :: Integer -> BinaryTree Integer


treeBuild n = undefined

:PV TIPVME CF QSPEVDJOH SFTVMUT UIBU MPPL MJLF UIF GPMMPXJOH

Prelude> treeBuild 0
Leaf
Prelude> treeBuild 1
Node Leaf 0 Leaf
$)"15&3  4*(/"-*/( "%7&34*5: 

Prelude> treeBuild 2
Node (Node Leaf 1 Leaf)
0
(Node Leaf 1 Leaf)
Prelude> treeBuild 3
Node (Node (Node Leaf 2 Leaf)
1
(Node Leaf 2 Leaf))
0
(Node (Node Leaf 2 Leaf)
1
(Node Leaf 2 Leaf))

0S JO B TMJHIUMZ EJƵFSFOU SFQSFTFOUBUJPO

0
/ \
1 1

0
/ \
1 1
/\ /\
2 2 2 2

(PPE XPSL
$)"15&3  4*(/"-*/( "%7&34*5: 

 %FƶOJUJPOT
 " IJHIFS LJOEFE UZQF UZQF JT BOZ UZQF XIPTF LJOE IBT B
GVODUJPO BSSPX JO JU BOE XIJDI DBO CF EFTDSJCFE BT B UZQF
DPOTUSVDUPS SBUIFS UIBO B UZQF DPOTUBOU 5IF GPMMPXJOH
UZQFT BSF PG B IJHIFS LJOE UIBO *

Maybe :: * -> *
[] :: * -> *
Either :: * -> * -> *
(->) :: * -> * -> *

5IF GPMMPXJOH BSF OPU

Int :: *
Char :: *
String :: *
[Char] :: *

5IJT JT OPU UP CF DPOGVTFE XJUI IJHIFS LJOEFE QPMZNPS


QIJTN XIJDI XFƊMM EJTDVTT MBUFS
$IBQUFS 

#VJMEJOH QSPKFDUT

8IFSFWFS UIFSF JT
NPEVMBSJUZ UIFSF JT UIF
QPUFOUJBM GPS
NJTVOEFSTUBOEJOH
)JEJOH JOGPSNBUJPO
JNQMJFT B OFFE UP DIFDL
DPNNVOJDBUJPO

"MBO 1FSMJT


$)"15&3  #6*-%*/( 130+&$54 

 .PEVMFT
)BTLFMM QSPHSBNT BSF PSHBOJ[FE JOUP NPEVMFT .PEVMFT DPO
UBJO UIF EBUBUZQFT UZQF TZOPOZNT UZQFDMBTTFT UZQFDMBTT JO
TUBODFT BOE WBMVFT ZPVƊWF EFƶOFE BU UIF UPQ MFWFM 5IFZ PƵFS
B NFBOT UP JNQPSU PUIFS NPEVMFT JOUP UIF TDPQF PG ZPVS QSP
HSBN BOE UIFZ BMTP DPOUBJO WBMVFT UIBU DBO CF FYQPSUFE UP
PUIFS NPEVMFT *G ZPVƊWF FWFS VTFE B MBOHVBHF XJUI OBNFT
QBDFT JUƊT UIF TBNF UIJOH
*O UIJT DIBQUFS XF XJMM CF CVJMEJOH B TNBMM JOUFSBDUJWF
IBOHNBOTUZMF HBNF 4UVEFOUT PG )BTLFMM PǒFO BTL XIBU LJOE
PG QSPKFDU UIFZ TIPVME XPSL PO BT B XBZ UP MFBSO )BTLFMM BOE
UIFZ XBOU UP KVNQ SJHIU JOUP UIF LJOE PG QSPHSBN UIFZƊSF
VTFE UP CVJMEJOH JO UIF MBOHVBHFT UIFZ BMSFBEZ LOPX 8IBU
NPTU PǒFO IBQQFOT JT UIF TUVEFOU SFBMJ[FT IPX NVDI UIFZ TUJMM
EPOƊU VOEFSTUBOE BCPVU )BTLFMM TIBLFT UIFJS ƶTU BU UIF TLZ BOE
DVSTFT )BTLFMMƊT WFSZ OBNF BOE BMM UIF FMJUJTU KFSLT XIP XSJUF
)BTLFMM BOE ƷFFT UP SFMBUJWF TBGFUZ /PCPEZ XBOUT UIBU )BTLFMM
JT TVƸDJFOUMZ EJƵFSFOU GSPN PUIFS MBOHVBHFT UIBU XF UIJOL
JUƊT CFTU UP TQFOE UJNF HFUUJOH QSFUUZ DPNGPSUBCMF XJUI IPX
)BTLFMM JUTFMG XPSLT CFGPSF USZJOH UP CVJME TVCTUBOUJBM QSPKFDUT
5IJT DIBQUFSƊT QSJNBSZ GPDVT JT OPU TP NVDI PO DPEF CVU PO
IPX UP TFU VQ B QSPKFDU JO )BTLFMM VTF UIF QBDLBHF NBOBHFS
LOPXO BT $BCBM CVJME UIF QSPKFDU XJUI 4UBDL BOE XPSL XJUI
NPEVMFT BT UIFZ BSF JO )BTLFMM 5IFSF BSF B GFX UJNFT XF BTL
ZPV UP JNQMFNFOU QBSU PG UIF IBOHNBO HBNF ZPVSTFMG CVU
$)"15&3  #6*-%*/( 130+&$54 

NVDI PG UIF DPEF JT BMSFBEZ XSJUUFO GPS ZPV BOE XFƊWF USJFE UP
FYQMBJO UIF TUSVDUVSF BT XFMM BT XF DBO BU UIJT QPJOU JO UIF CPPL
4PNF PG JU ZPV XPOƊU QSPQFSMZ VOEFSTUBOE VOUJM XFƊWF DPWFSFE
BU MFBTU NPOBET BOE IO #VU JG ZPV ƶOJTI UIF DIBQUFS GFFMJOH
MJLF ZPV OPX LOPX IPX UP TFU VQ B QSPKFDU FOWJSPONFOU BOE
HFU UIJOHT SVOOJOH UIFO UIJT DIBQUFS XJMM IBWF BDDPNQMJTIFE
JUT HPBM BOE XFƊMM BMM HP PƵ BOE UBLF B NVDI OFFEFE NJECPPL
OBQ
+VTU USZ UP SFMBY BOE IBWF GVO XJUI UIJT :PVƊWF FBSOFE JU
BǒFS UIPTF CJOBSZ USFF FYFSDJTFT
*O UIJT DIBQUFS XFƊMM DPWFS

Ƒ XSJUJOH )BTLFMM QSPHSBNT XJUI NPEVMFT

Ƒ VTJOH UIF $BCBM QBDLBHF NBOBHFS

Ƒ CVJMEJOH PVS QSPKFDU XJUI 4UBDL

Ƒ DPOWFOUJPOT BSPVOE )BTLFMM QSPKFDU PSHBOJ[BUJPO

Ƒ CVJMEJOH B TNBMM JOUFSBDUJWF HBNF

/PUF UIBU ZPVƊMM OFFE UP IBWF 4UBDL BOE (JU UP GPMMPX BMPOH
XJUI UIF JOTUSVDUJPOT JO UIJT DIBQUFS 8FƊMM CF VTJOH git UP
EPXOMPBE BO FYBNQMF QSPKFDU %FQFOEJOH PO ZPVS MFWFM PG
QSJPS FYQFSJFODF TPNF PG UIJT NBZ OPU CF OFX JOGPSNBUJPO

http://haskellstack.org

https://git-scm.com/
$)"15&3  #6*-%*/( 130+&$54 

GPS ZPV 'FFM GSFF UP NPWF BT RVJDLMZ UISPVHI UIJT NBUFSJBM BT


GFFMT DPNGPSUBCMF

 .BLJOH QBDLBHFT XJUI 4UBDL


5IF )BTLFMM $BCBM PS $PNNPO "SDIJUFDUVSF GPS #VJMEJOH "Q
QMJDBUJPOT BOE -JCSBSJFT JT B QBDLBHF NBOBHFS " QBDLBHF JT
B QSPHSBN ZPVƊSF CVJMEJOH JODMVEJOH BMM PG JUT NPEVMFT BOE
EFQFOEFODJFT XIFUIFS ZPVƊWF XSJUUFO JU PS ZPVƊSF CVJMEJOH
TPNFPOF FMTFƊT QSPHSBN " QBDLBHF IBT EFQFOEFODJFT XIJDI BSF
UIF JOUFSMJOLFE FMFNFOUT PG UIBU QSPHSBN UIF PUIFS QBDLBHFT
BOE MJCSBSJFT JU NBZ EFQFOE PO BOE BOZ UFTUT BOE EPDVNFOUB
UJPO BTTPDJBUFE XJUI UIF QSPKFDU $BCBM FYJTUT UP IFMQ PSHBOJ[F
BMM UIJT BOE NBLF TVSF BMM EFQFOEFODJFT BSF QSPQFSMZ JO TDPQF
4UBDL JT B DSPTTQMBUGPSN QSPHSBN GPS EFWFMPQJOH )BTLFMM
QSPKFDUT *U JT BJNFE BU )BTLFMMFST CPUI OFX BOE FYQFSJFODFE
BOE JU IFMQT ZPV NBOBHF CPUI QSPKFDUT NBEF VQ PG NVMUJQMF
QBDLBHFT BT XFMM BT JOEJWJEVBM QBDLBHFT XIFSFBT $BCBM FYJTUT
QSJNBSJMZ UP EFTDSJCF B TJOHMF QBDLBHF XJUI B $BCBM ƶMF UIBU
IBT UIF .cabal ƶMF FYUFOTJPO
4UBDL JT CVJMU PO UPQ PG $BCBM JO TPNF JNQPSUBOU TFOTFT
TP XF XJMM TUJMM CF XPSLJOH XJUI .cabal ƶMFT )PXFWFS 4UBDL
TJNQMJƶFT UIF QSPDFTT TPNFXIBU FTQFDJBMMZ JO MBSHF QSPKFDUT
XJUI NVMUJQMF EFQFOEFODJFT CZ BMMPXJOH ZPV UP CVJME UIPTF
MBSHF MJCSBSJFT POMZ PODF BOE VTF UIFN BDSPTT QSPKFDUT 4UBDL
BMTP SFMJFT PO BO -54 MPOH UFSN TVQQPSU
TOBQTIPU PG )BTLFMM
$)"15&3  #6*-%*/( 130+&$54 

QBDLBHFT GSPN 4UBDLBHF UIBU BSF HVBSBOUFFE UP XPSL UPHFUIFS


VOMJLF QBDLBHFT GSPN )BDLBHF XIJDI NBZ IBWF DPOƷJDUJOH
EFQFOEFODJFT
8IJMF UIF )BTLFMM DPNNVOJUZ EPFT OPU IBWF B QSFTDSJCFE
QSPKFDU MBZPVU XF SFDPNNFOE UIF CBTJD TUSVDUVSF FNCPEJFE
JO UIF 4UBDL UFNQMBUFT

 8PSLJOH XJUI B CBTJD QSPKFDU


8FƊSF HPJOH UP TUBSU MFBSOJOH $BCBM BOE 4UBDL CZ CVJMEJOH B
TBNQMF QSPKFDU DBMMFE hello 5P NBLF UIJT MFTT UFEJPVT XFƊSF
HPJOH UP VTF git UP DIFDLPVU UIF TBNQMF QSPKFDU *O BO BQQSP
QSJBUF EJSFDUPSZ GPS TUPSJOH ZPVS QSPKFDUT ZPVƊMM XBOU UP git
clone UIF SFQPTJUPSZ https://github.com/haskellbook/hello

#VJMEJOH UIF QSPKFDU


$IBOHF JOUP UIF QSPKFDU EJSFDUPSZ UIBU UIF git clone JOWPDBUJPO
DSFBUFE

$ cd hello

:PV DPVME FEJU UIF hello.cabal ƶMF 5IFSF ZPV DBO SFQMBDF
ƌ:PVS /BNF )FSFƍ XJUIƒZPVS BDUVBM OBNF 8FƊMM OFYU CVJME
PVS QSPKFDU

https://www.stackage.org/
$)"15&3  #6*-%*/( 130+&$54 

$ stack build

*G JU DPNQMBJOT BCPVU OFFEJOH ()$ UP CF JOTUBMMFE EPOƊU


QBOJD 1BSU PG UIF CFOFƶU PG 4UBDL JT UIBU JU DBO NBOBHF ZPVS
()$ JOTUBMMT GPS ZPV #FGPSF SFBUUFNQUJOH stack build EP UIF
GPMMPXJOH

$ stack setup

5IF setup DPNNBOE GPS 4UBDL EFUFSNJOFT XIBU WFSTJPO PG


()$ ZPV OFFE CBTFE PO UIF -54 TOBQTIPU TQFDJƶFE JO UIF
stack.yaml ƶMF PG ZPVS QSPKFDU 5IF stack.yaml ƶMF JT VTFE UP
EFUFSNJOF UIF WFSTJPOT PG ZPVS QBDLBHFT BOE XIBU WFSTJPO
PG ()$ UIFZƊMM XPSL CFTU XJUI *G ZPV EJEOƊU OFFE UP EP UIJT
JUƊT QPTTJCMF ZPV IBE B DPNQBUJCMF WFSTJPO PG ()$ BMSFBEZ
JOTUBMMFE PS UIBU ZPVƊE SVO TFUVQ GPS BO -54 TOBQTIPU UIBU
OFFEFE UIF TBNF WFSTJPO PG ()$ JO UIF QBTU 5P MFBSO NPSF
BCPVU UIJT DIFDL PVU UIF 4UBDLBHF XFCTJUF

-PBEJOH BOE SVOOJOH DPEF GSPN UIF 3&1-


)BWJOH EPOF UIBU OFYU XFƊMM ƶSF VQ UIF 3&1-

$ stack ghci
[... some other noise...]
Ok, modules loaded: Main.
Prelude> :l Main
$)"15&3  #6*-%*/( 130+&$54 

[1 of 1] Compiling Main
Ok, modules loaded: Main.
Prelude> main
hello world

4P JO UIF BCPWF XF TVDDFTTGVMMZ TUBSUFE B ()$J 3&1- BXBSF


PG PVS QSPKFDU MPBEFE PVS Main NPEVMF BOE UIFO SBO UIF main
GVODUJPO 6TJOH 4UBDLƊT ()$J JOUFHSBUJPO UP ƶSF VQ B 3&1-
EPFTOƊU KVTU MFU VT MPBE BOE SVO DPEF JO PVS QSPKFDU CVU BMTP
FOBCMFT VT UP NBLF VTF PG PVS QSPKFDUƊT EFQFOEFODJFT 8FƊMM
EFNPOTUSBUF UIJT MBUFS

TUBDL FYFD
8IFO ZPV SBO build FBSMJFS ZPV NBZ IBWF TFFO TPNFUIJOH
MJLF

Linking .stack-work/dist/{...noise...}/hello

5IJT OPJTF JT 4UBDL DPNQJMJOH BO FYFDVUBCMF CJOBSZ BOE MJOL


JOH UP JU :PV DBO KVTU UZQF UIF GVMM QBUI UIBU 4UBDL NFOUJPOFE
JO PSEFS UP SVO UIF CJOBSZ CVU UIFSFƊT BO FBTJFS XBZ ƈ exec
'SPN PVS QSPKFDU EJSFDUPSZ DPOTJEFS UIF GPMMPXJOH

$ hello
zsh: command not found: hello
$ stack exec -- hello
hello world
$)"15&3  #6*-%*/( 130+&$54 

4UBDL LOPXT XIBU QBUIT BOZ FYFDVUBCMFT NJHIU CF MPDBUFE JO


TP VTJOH 4UBDLƊT exec DPNNBOE TBWFT ZPV UIF IBTTMF PG UZQJOH
PVU B QPUFOUJBMMZ WFSCPTF QBUI

&YFDVUBCMF TUBO[BT JO $BCBM ƶMFT


4UBDL DSFBUFE BO FYFDVUBCMF FBSMJFS CFDBVTF PG UIF GPMMPXJOH
TUBO[B JO UIF hello.cabal ƶMF

executable hello
-- [1]
hs-source-dirs: src
-- [2]
main-is: Main.hs
-- [3]
default-language: Haskell2010
-- [4]
build-depends: base >= 4.7 && < 5
-- [5]

 5IJT OBNF GPMMPXJOH UIF EFDMBSBUJPO PG BO FYFDVUBCMF TUBO[B


UFMMT 4UBDL PS $BCBM XIBU UP OBNF UIF CJOBSZ PS FYFDVUBCMF
JU DSFBUFT

 5FMMT UIJT TUBO[B XIFSF UP MPPL GPS TPVSDF DPEF ƈ JO UIJT


DBTF UIF TSD TVCEJSFDUPSZ
$)"15&3  #6*-%*/( 130+&$54 

 &YFDVUJPO PG UIJT CJOBSZ TIPVME CFHJO CZ MPPLJOH GPS B main


GVODUJPO JOTJEF B ƶMF OBNFE Main XJUI UIF NPEVMF OBNF
Main /PUF UIBU NPEVMF OBNFT IBWF UP NBUDI ƶMFOBNFT
:PVS DPNQJMFS OPU KVTU 4UBDL
XJMM SFKFDU VTJOH B ƶMF UIBU
JTOƊU B Main NPEVMF BT UIF FOUSZ QPJOU UP FYFDVUJOH UIF
QSPHSBN "MTP OPUF UIBU JUƊMM MPPL GPS UIF Main.hs ƶMF VOEFS
BMM EJSFDUPSJFT ZPV TQFDJƶFE JO ITTPVSDFEJST 4JODF XF
TQFDJƶFE POMZ POF JUƊMM ƶOE UIJT JO TSD.BJOIT XIJDI JT
PVS POMZ TPVSDF ƶMF SJHIU OPX BOZXBZ

 %FƶOFT UIF WFSTJPO PG UIF )BTLFMM TUBOEBSE UP FYQFDU /PU


WFSZ JOUFSFTUJOH BOE EPFTOƊU EP NVDI NPTUMZ CPJMFSQMBUF
CVU OFDFTTBSZ

 5IJT JT VTVBMMZ B NFBUJFS QBSU PG BOZ $BCBM TUBO[B XIFUIFS


JUƊT BO FYFDVUBCMF MJCSBSZ PS UFTU TVJUF 5IJT FYBNQMF CBTF

JT SFBMMZ UIF CBSF NJOJNVN PS CBTFMJOF EFQFOEFODZ JO


BMNPTU BOZ )BTLFMM QSPKFDU BT ZPV DBOƊU SFBMMZ HFU BOZUIJOH
EPOF XJUIPVU UIF CBTF MJCSBSZ 8FƊMM TIPX ZPV IPX UP BEE
BOE JOTUBMM EFQFOEFODJFT MBUFS

" TJEFCBS BCPVU FYFDVUBCMFT BOE MJCSBSJFT 0VS QSPKFDU IFSF


POMZ IBT BO FYFDVUBCMF TUBO[B XIJDI JT BQQSPQSJBUF GPS NBL
JOH B DPNNBOEMJOF BQQMJDBUJPO XIJDI XJMM CF SVO BOE VTFE
8IFO XFƊSF XSJUJOH DPEF XF XBOU QFPQMF UP CF BCMF UP SFVTF
JO PUIFS QSPKFDUT XF OFFE B MJCSBSZ TUBO[B JO UIF $BCBM ƶMF
BOE UP DIPPTF XIJDI NPEVMFT XF XBOU UP FYQPTF &YFDVUBCMFT
$)"15&3  #6*-%*/( 130+&$54 

BSF BQQMJDBUJPOT UIBU UIF PQFSBUJOH TZTUFN XJMM SVO EJSFDUMZ


XIJMF TPǒXBSF MJCSBSJFT BSF DPEF BSSBOHFE JO B NBOOFS TP UIBU
UIFZ DBO CF SFVTFE CZ UIF DPNQJMFS JO UIF CVJMEJOH PG PUIFS
MJCSBSJFT BOE QSPHSBNT

 .BLJOH PVS QSPKFDU B MJCSBSZ


'JSTU XFƊSF HPJOH UP BEE B MJCSBSZ TUBO[B UP hello.cabal

library
hs-source-dirs: src
exposed-modules: Hello
build-depends: base >= 4.7 && < 5
default-language: Haskell2010

5IFO XFƊSF HPJOH UP DSFBUF B ƶMF MPDBUFE BU src/Hello.hs

module Hello where

sayHello :: IO ()
sayHello = do
putStrLn "hello world"

5IFO XFƊSF HPJOH UP DIBOHF PVS Main NPEVMF UP VTF UIJT


MJCSBSZ GVODUJPO
$)"15&3  #6*-%*/( 130+&$54 

module Main where

import Hello

main :: IO ()
main = do
sayHello

*G XF USZ UP CVJME BOE SVO UIJT OPX JUƊMM XPSL

$ stack build
$ stack exec hello
hello world

#VU XIBU JG XF IBE NBEF B TFQBSBUF exe EJSFDUPSZ

$ mkdir exe
$ mv src/Main.hs exe/Main.hs

5IFO XF OFFE UP FEJU UIF $BCBM ƶMF UP MFU JU LOPX PVS hello
FYFDVUBCMF VTFT UIF exe EJSFDUPSZ

executable hello
hs-source-dirs: exe
main-is: Main.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
$)"15&3  #6*-%*/( 130+&$54 

*G ZPV UIFO BUUFNQU UP CVJME UIJT JU XJMM GBJM

hello/exe/Main.hs:3:8:
Could not find module ‘Hello’
It is a member of the hidden package
‘hello-0.1.0.0@hello_IJIUuynUbgsHAquBKsAsb5’.
Perhaps you need to add ‘hello’ to the
build-depends in your .cabal file.
Use -v to see a list of the files searched for.

8F IBWF UXP QBUIT GPS ƶYJOH UIJT POF CFUUFS UIBO UIF PUIFS
0OF XBZ JT UP TJNQMZ BEE src UP UIF TPVSDF EJSFDUPSJFT UIF
FYFDVUBCMF JT QFSNJUUFE UP TFBSDI #VU JU UVSOT PVU UIBU $BCBMƊT
TVHHFTUJPO IFSF JT QSFDJTFMZ SJHIU 5IF CFUUFS XBZ UP ƶY UIJT JT
UP SFTQFDU UIF CPVOEBSJFT PG UIF MJCSBSZ BOE FYFDVUBCMF BOE
JOTUFBE UP BEE ZPVS PXO MJCSBSZ BT B EFQFOEFODZ

executable hello
hs-source-dirs: exe
main-is: Main.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
, hello

5IF CVJME XJMM OPX TVDDFFE 5IJT BMTP NBLFT JU FBTJFS UP


LOPX XIFO ZPV OFFE UP DIBOHF XIBU JT FYQPTFE PS FYQPSUFE
JO ZPVS MJCSBSZ CFDBVTF ZPVƊSF VTJOH ZPVS PXO JOUFSGBDF
$)"15&3  #6*-%*/( 130+&$54 

 .PEVMF FYQPSUT


#Z EFGBVMU XIFO ZPV EPOƊU TQFDJGZ BOZ FYQPSUT JO B NPEVMF
FWFSZ UPQMFWFM CJOEJOH JT FYQPSUFE BOE DBO CF JNQPSUFE CZ
BOPUIFS NPEVMF 5IJT JT UIF DBTF JO PVS Hello NPEVMF

module Hello where

sayHello :: IO ()
sayHello = do
putStrLn "hello world"

#VU XIBU IBQQFOT JG XF TQFDJGZ BO FNQUZ FYQPSU MJTU

module Hello
()
where

sayHello :: IO ()
sayHello = do
putStrLn "hello world"

8FƊMM HFU UIF GPMMPXJOH FSSPS JG XF BUUFNQU UP CVJME JU

Not in scope: ‘sayHello’

5P ƶY UIBU FYQMJDJUMZ XF BEE UIF UPQ MFWFM CJOEJOH UP UIF


FYQPSU MJTU
$)"15&3  #6*-%*/( 130+&$54 

module Hello
( sayHello )
where

sayHello :: IO ()
sayHello = do
putStrLn "hello world"

/PX UIF sayHello GVODUJPO XJMM CF FYQPSUFE *U TFFNT QPJOU


MFTT JO B NPEVMF MJLF UIJT CVU JO CJHHFS QSPKFDUT JU TPNFUJNFT
NBLFT TFOTF UP TQFDJGZ ZPVS FYQPSUT JO UIJT XBZ

&YQPTJOH NPEVMFT
'JSTU XFƊMM BEE B OFX NPEVMF XJUI B OFX *0 BDUJPO GPS PVS main
BDUJPO UP SVO

-- src/DogsRule.hs
module DogsRule
( dogs )
where

dogs :: IO ()
dogs = do
putStrLn "Who's a good puppy?!"
putStrLn "YOU ARE!!!!!"
$)"15&3  #6*-%*/( 130+&$54 

5IFO XFƊMM DIBOHF PVS Main NPEVMF UP NBLF VTF PG UIJT

module Main where

import DogsRule
import Hello

main :: IO ()
main = do
sayHello
dogs

#VU JG XF BUUFNQU UP CVJME UIJT XFƊMM HFU UIF GPMMPXJOH FSSPS

Could not find module ‘DogsRule’

"T XF EJE FBSMJFS XJUI PVS MJCSBSZ TUBO[B XF OFFE UP BMTP


FYQPTF UIF DogsRule NPEVMF

library
hs-source-dirs: src
exposed-modules: DogsRule
, Hello
build-depends: base >= 4.7 && < 5
default-language: Haskell2010

/PX JU TIPVME CF BCMF UP ƶOE PVS WFSZ JNQPSUBOU EPH QSBJT


JOH
$)"15&3  #6*-%*/( 130+&$54 

 .PSF PO JNQPSUJOH NPEVMFT


*NQPSUJOH NPEVMFT CSJOHT NPSF GVODUJPOT JOUP TDPQF CFZPOE
UIPTF BWBJMBCMF JO UIF TUBOEBSE 1SFMVEF *NQPSUFE NPEVMFT
BSF UPQMFWFM EFDMBSBUJPOT 5IF FOUJUJFT JNQPSUFE BT QBSU PG
UIPTF EFDMBSBUJPOT MJLF PUIFS UPQMFWFM EFDMBSBUJPOT IBWF TDPQF
UISPVHIPVU UIF NPEVMF BMUIPVHI UIFZ DBO CF TIBEPXFE CZ
MPDBM CJOEJOHT 5IF FƵFDU PG NVMUJQMF JNQPSU EFDMBSBUJPOT JT DV
NVMBUJWF CVU UIF PSEFSJOH PG JNQPSU EFDMBSBUJPOT JT JSSFMFWBOU
"O FOUJUZ JT JO TDPQF GPS UIF FOUJSF NPEVMF JG JU JT JNQPSUFE CZ
BOZ PG UIF JNQPSU EFDMBSBUJPOT
*O QSFWJPVT DIBQUFST XFƊWF CSPVHIU GVODUJPOT MJLF bool BOE
toUpper JOUP TDPQF GPS FYFSDJTFT CZ JNQPSUJOH UIF NPEVMFT UIFZ
BSF QBSU PG Data.Bool BOE Data.Char SFTQFDUJWFMZ
-FUƊT SFGSFTI PVS NFNPSZ PG IPX UP EP UIJT JO ()$J 5IF
:browse DPNNBOE BMMPXT VT UP TFF XIBU GVODUJPOT BSF JODMVEFE
JO UIF OBNFE NPEVMF XIJMF JNQPSUJOH UIF NPEVMF BMMPXT VT
UP BDUVBMMZ VTF UIPTF GVODUJPOT :PV DBO CSPXTF NPEVMFT UIBU
ZPV IBWFOƊU JNQPSUFE ZFU XIJDI DBO CF VTFGVM JG ZPVƊSF OPU
TVSF XIJDI NPEVMF UIF GVODUJPO ZPVƊSF MPPLJOH GPS JT JO

Prelude> :browse Data.Bool


bool :: a -> a -> Bool -> a
(&&) :: Bool -> Bool -> Bool
data Bool = False | True
not :: Bool -> Bool
$)"15&3  #6*-%*/( 130+&$54 

otherwise :: Bool
(||) :: Bool -> Bool -> Bool

Prelude> import Data.Bool

Prelude> :t bool
bool :: a -> a -> Bool -> a

*O UIF FYBNQMF BCPWF XF VTFE BO VORVBMJƶFE JNQPSU PG


FWFSZUIJOH JO Data.Bool 8IBU JG XF POMZ XBOUFE bool GSPN
Data.Bool
'JSTU XFƊSF HPJOH UP UVSO PƵ 1SFMVEF TP UIBU XF EPOƊU IBWF
BOZ PG UIF EFGBVMU JNQPSUT 8F XJMM VTF BOPUIFS QSBHNB PS
MBOHVBHF FYUFOTJPO XIFO XF TUBSU ()$J UP UVSO 1SFMVEF PƵ
:PVƊWF QSFWJPVTMZ TFFO IPX UP VTF MBOHVBHF FYUFOTJPOT JO
TPVSDF ƶMFT CVU OPX XFƊMM FOUFS -XNoImplicitPrelude SJHIU XIFO
XF FOUFS PVS 3&1-

-- Do this outside of any projects

$ stack ghci --ghci-options -XNoImplicitPrelude


Prelude>

8F DBO DIFDL UIBU bool BOE not BSF OPU JO TDPQF ZFU

Prelude> :t bool
<interactive>:1:1: Not in scope: ‘bool’
$)"15&3  #6*-%*/( 130+&$54 

Prelude> :t not
<interactive>:1:1: Not in scope: ‘not’

/FYU XFƊMM EP B TFMFDUJWF JNQPSU GSPN Data.Bool TQFDJGZJOH


UIBU XF POMZ XBOU UP JNQPSU bool

Prelude> import Data.Bool (bool)


Prelude> :t bool
bool :: a -> a -> GHC.Types.Bool -> a
Prelude> :t not
<interactive>:1:1: Not in scope: ‘not’

/PX OPSNBMMZ JO UIF TUBOEBSE 1SFMVEF not JT JO TDPQF BM


SFBEZ CVU bool JT OPU 4P ZPV DBO TFF UIBU CZ UVSOJOH PƵ 1SFMVEF
UBLJOH JUT TUBOEBSE GVODUJPOT PVU PG TDPQF BOE UIFO JNQPSUJOH
POMZ bool XF OP MPOHFS IBWF UIF TUBOEBSE not GVODUJPO JO TDPQF
:PV DBO JNQPSU POF PS NPSF GVODUJPOT GSPN B NPEVMF PS
MJCSBSZ 5IF TZOUBY JT KVTU BT XF KVTU EFNPOTUSBUFE XJUI ()$J
CVU ZPVS JNQPSU EFDMBSBUJPOT IBWF UP CF BU UIF CFHJOOJOH PG
B NPEVMF 1VUUJOH import Data.Char (toUpper) JO UIF JNQPSU
EFDMBSBUJPOT PG B NPEVMF XJMM FOTVSF UIBU toUpper CVU OPU BOZ
PG UIF PUIFS FOUJUJFT DPOUBJOFE JO Data.Char JT JO TDPQF GPS UIBU
NPEVMF
'PS UIF FYBNQMFT JO UIF OFYU TFDUJPO ZPVƊMM XBOU Prelude
CBDL PO TP QMFBTF SFTUBSU ()$J CFGPSF QSPDFFEJOH
$)"15&3  #6*-%*/( 130+&$54 

2VBMJƶFE JNQPSUT
8IBU JG ZPV XBOUFE UP LOPX XIFSF TPNFUIJOH ZPV JNQPSUFE
DBNF GSPN JO UIF DPEF UIBU VTFT JU 8F DBO VTF RVBMJƶFE
JNQPSUT UP NBLF UIF OBNFT NPSF FYQMJDJU
8F VTF UIF qualified LFZXPSE JO PVS JNQPSUT UP EP UIJT
4PNFUJNFT ZPVƊMM IBWF TUVƵ XJUI UIF TBNF OBNF JNQPSUFE
GSPN UXP EJƵFSFOU NPEVMFT RVBMJGZJOH ZPVS JNQPSUT JT B DPN
NPO XBZ PG EFBMJOH XJUI UIJT 8FƊMM HP UISPVHI BO FYBNQMF PG
IPX ZPV NJHIU VTF B RVBMJƶFE JNQPSU

Prelude> import qualified Data.Bool


Prelude> :t bool

<interactive>:1:1:
Not in scope: ‘bool’
Perhaps you meant ‘Data.Bool.bool’

Prelude> :t Data.Bool.bool
Data.Bool.bool :: a -> a -> Data.Bool.Bool -> a

Prelude> :t Data.Bool.not
Data.Bool.not :: Data.Bool.Bool -> Data.Bool.Bool

*O UIF DBTF PG import qualified Data.Bool FWFSZUIJOH GSPN


Data.Bool JT JO TDPQF CVU POMZ XIFO BDDFTTFE XJUI UIF GVMM
$)"15&3  #6*-%*/( 130+&$54 

Data.Bool OBNFTQBDF /PX XF BSF NBSLJOH XIFSF UIF GVOD


UJPOT UIBU XFƊSF VTJOH DBNF GSPN XIJDI DBO CF VTFGVM
8F DBO BMTP QSPWJEF BMJBTFT PS BMUFSOBUF OBNFT GPS PVS NPE
VMFT XIFO XF RVBMJGZ UIFN TP XF EPOƊU IBWF UP UZQF PVU UIF
GVMM OBNFTQBDF

Prelude> import qualified Data.Bool as B


Prelude> :t bool

<interactive>:1:1:
Not in scope: ‘bool’
Perhaps you meant ‘B.bool’

Prelude> :t B.bool
B.bool :: a -> a -> B.Bool -> a

Prelude> :t B.not
B.not :: B.Bool -> B.Bool

:PV DBO EP RVBMJƶFE JNQPSUT JO UIF JNQPSU EFDMBSBUJPOT BU


UIF CFHJOOJOH PG ZPVS NPEVMF JO UIF TBNF XBZ

4FUUJOH UIF 1SFMVEF QSPNQU 8IFO ZPV JNQPSUFE Data.Bool


BT B BCPWF ZPV NBZ IBWF TFFO ZPVS QSPNQU DIBOHF

Prelude> import qualified Data.Bool as B


Prelude B>
$)"15&3  #6*-%*/( 130+&$54 

"OE JG ZPV EPOƊU XBOU UP VOMPBE UIF JNQPSUFE NPEVMFT


CFDBVTF ZPV XBOU UIFN BMM UP TUBZ JO TDPQF
ZPVS QSPNQU
DPVME LFFQ HSPXJOH

Prelude B> import Data.Char


Prelude B Data.Char>

3FNJOEFS ZPV DBO VTF :m UP VOMPBE UIF NPEVMFT XIJDI


EPFT PG DPVSTF QSFWFOU UIF QSPNQU GSPN HSPXJOH FWFS MBSHFS
CVU BMTP XFMM VOMPBET UIF NPEVMFT TP UIFZƊSF OPU JO TDPQF
BOZNPSF

*G ZPV XBOU UP QSFWFOU UIF FWFSHSPXJOH QSPNQU ZPV DBO


VTF UIF :set DPNNBOE UP TFU UIF QSPNQU UP XIBUFWFS ZPV
QSFGFS

Prelude> :set prompt "Lambda> "


Lambda> import Data.Char
Lambda> :t B.bool
B.bool :: a -> a -> Bool -> a

"T ZPV DBO TFF Data.Bool JT TUJMM JO TDPQF BT B CVU JU EPFTOƊU


TIPX VQ JO PVS QSPNQU :PV DBO TFU ZPVS Prelude QSPNQU
QFSNBOFOUMZ JG ZPV XJTI CZ DIBOHJOH JU JO ZPVS ()$J DPOƶH
VSBUJPO ƶMF CVU JOTUSVDUJPOT GPS EPJOH UIBU BSF TPNFXIBU PVU
PG UIF TDPQF PG UIF DVSSFOU DIBQUFS
$)"15&3  #6*-%*/( 130+&$54 

*OUFSNJTTJPO $IFDL ZPVS VOEFSTUBOEJOH


)FSF JT UIF JNQPSU MJTU GSPN POF PG UIF NPEVMFT JO $ISJTƊT
MJCSBSZ DBMMFE CMBDLUJQ

import qualified Control.Concurrent


as CC
import qualified Control.Concurrent.MVar
as MV
import qualified Data.ByteString.Char8
as B
import qualified Data.Locator
as DL

import qualified Data.Time.Clock.POSIX


as PSX
import qualified Filesystem
as FS
import qualified Filesystem.Path.CurrentOS
as FPC
import qualified Network.Info
as NI
$)"15&3  #6*-%*/( 130+&$54 

import qualified Safe


import Control.Exception (mask, try)
import Control.Monad (forever, when)
import Data.Bits
import Data.Bits.Bitwise (fromListBE)
import Data.List.Split (chunksOf)
import Database.Blacktip.Types
import System.IO.Unsafe (unsafePerformIO)

'PS PVS QVSQPTFT SJHIU OPX JU EPFT OPU NBUUFS XIFUIFS ZPV
BSF GBNJMJBS XJUI UIF NPEVMFT SFGFSFODFE JO UIF JNQPSU MJTU
-PPL BU UIF EFDMBSBUJPOT BOE BOTXFS UIF RVFTUJPOT CFMPX

 8IBU GVODUJPOT BSF CFJOH JNQPSUFE GSPN Control.Monad

 8IJDI JNQPSUT BSF CPUI VORVBMJƶFE BOE JNQPSUFE JO UIFJS


FOUJSFUZ

 'SPN UIF OBNF XIBU EP ZPV TVQQPTF JNQPSUJOH #MBDL


UJQƊT 5ZQFT NPEVMF CSJOHT JO

 /PX MFUƊT DPNQBSF B TNBMM QBSU PG CMBDLUJQƊT DPEF UP UIF


BCPWF JNQPSU MJTU
$)"15&3  #6*-%*/( 130+&$54 

writeTimestamp :: MV.MVar ServerState


-> FPC.FilePath
-> IO CC.ThreadId
writeTimestamp s path = do
CC.forkIO go
where go = forever $ do
ss <- MV.readMVar s
mask $ \_ -> do
FS.writeFile path (B.pack (show (ssTime ss)))
-- sleep for 1 second
CC.threadDelay 1000000

B
5IF UZQF TJHOBUVSF SFGFST UP UISFF BMJBTFE JNQPSUT
8IBU NPEVMFT BSF OBNFE JO UIPTF BMJBTFT
C
8IJDI JNQPSU EPFT FS.writeFile SFGFS UP
D
8IJDI JNQPSU EJE forever DPNF GSPN

 .BLJOH PVS QSPHSBN JOUFSBDUJWF


/PX XFƊSF HPJOH UP NBLF PVS QSPHSBN BTL GPS ZPVS OBNF UIFO
HSFFU ZPV CZ OBNF 'JSTU XFƊMM SFXSJUF PVS sayHello GVODUJPO
UP UBLF BO BSHVNFOU

sayHello :: String -> IO ()


sayHello name = putStrLn ("Hi " ++ name ++ "!")
$)"15&3  #6*-%*/( 130+&$54 

/PUF XF QBSFOUIFTJ[FE UIF BQQFOEJOH (++) GVODUJPO PG UIF


String BSHVNFOU UP putStrLn
/FYU XFƊMM DIBOHF main UP HFU UIF VTFSƊT OBNF

-- src/Main.hs

main :: IO ()
main = do
name <- getLine
sayHello name
dogs

5IFSF BSF B DPVQMF PG OFX UIJOHT IFSF 8FƊSF VTJOH TPNF


UIJOH DBMMFE EP TZOUBY XIJDI JT TZOUBDUJD TVHBS 8F VTF do
JOTJEF GVODUJPOT UIBU SFUVSO IO JO PSEFS UP TFRVFODF TJEF FƵFDUT
JO B DPOWFOJFOU TZOUBY -FUƊT EFDPNQPTF XIBUƊT HPJOH PO IFSF

main :: IO ()
main = do
-- [1]
name <- getLine
-- [4] [3] [2]
sayHello name
-- [5]
dogs
-- [6]
$)"15&3  #6*-%*/( 130+&$54 

 5IF do IFSF CFHJOT UIF CMPDL

 getLine IBT UZQF IO String CFDBVTF JU NVTU QFSGPSN *0


JOQVUPVUQVU TJEF FƵFDUT
JO PSEFS UP PCUBJO UIF String
getLine JT XIBU XJMM BMMPX ZPV UP FOUFS ZPVS OBNF UP CF
VTFE JO UIF main GVODUJPO

 <- JO B do CMPDL JT QSPOPVODFE CJOE 8FƊMM FYQMBJO XIBU


UIJT JT BOE IPX JU XPSLT JO UIF DIBQUFST PO Monad BOE IO

 5IF SFTVMU PG CJOEJOH <-


PWFS UIF IO String JT String 8F
CPVOE JU UP UIF WBSJBCMF name 3FNFNCFS getLine IBT UZQF
IO String name IBT UZQF String

 sayHello FYQFDUT BO BSHVNFOU String XIJDI JT UIF UZQF PG


name CVU OPU getLine

 dogs FYQFDUT OPUIJOH BOE JT BO IO BDUJPO PG UZQF IO ()


XIJDI ƶUT UIF PWFSBMM UZQF PG main

/PX XFƊMM ƶSF PƵ B CVJME

$ stack build

"OE SVO UIF QSPHSBN

$ stack exec hello



.VDI MJLF BDUVBM EPHT
$)"15&3  #6*-%*/( 130+&$54 

"ǒFS ZPV IJU FOUFS UIF QSPHSBN JT HPJOH UP XBJU GPS ZPVS
JOQVU :PVƊMM KVTU TFF UIF DVSTPS CMJOLJOH PO UIF MJOF XBJUJOH
GPS ZPV UP FOUFS ZPVS OBNF "T TPPO BT ZPV EP BOE IJU FOUFS
JU TIPVME HSFFU ZPV BOE UIFO SBWF BCPVU UIF XPOEFSGVMOFTT PG
B EPH

8IBU JG XF USJFE UP QBTT HFU-JOF UP TBZ)FMMP *G XF USJFE UP


XSJUF main XJUIPVU UIF VTF PG do TZOUBY QBSUJDVMBSMZ XJUIPVU
VTJOH <- TVDI BT JO UIF GPMMPXJOH FYBNQMF

main :: IO ()
main = sayHello getLine

8FƊE HFU UIF GPMMPXJOH UZQF FSSPS

$ stack build
[2 of 2] Compiling Main

src/Main.hs:8:17:
Couldn't match type ‘IO String’ with ‘[Char]’
Expected type: String
Actual type: IO String
In the first argument of ‘sayHello’, namely ‘getLine’
In the expression: sayHello getLine

5IJT JT CFDBVTF getLine JT BO IO BDUJPO XJUI UZQF IO String


XIFSFBT sayHello FYQFDUT B WBMVF PG UZQF String 8F IBWF UP
$)"15&3  #6*-%*/( 130+&$54 

VTF <- UP CJOE PWFS UIF IO UP HFU UIF TUSJOH UIBU XF XBOU UP
QBTT UP sayHello 5IJT XJMM CF FYQMBJOFE JO NPSF EFUBJM ƈ B CJU
NPSF EFUBJM MBUFS JO UIF DIBQUFS BOE B MPU NPSF EFUBJM JO B MBUFS
DIBQUFS

"EEJOH B QSPNQU
-FUƊT NBLF PVS QSPHSBN B CJU FBTJFS UP VTF CZ BEEJOH B QSPNQU
UIBU UFMMT VT PVS QSPHSBN JT FYQFDUJOH JOQVU 8F KVTU OFFE UP
DIBOHF main

module Main where

import DogsRule
import Hello
import System.IO

main :: IO ()
main = do
hSetBuffering stdout NoBuffering
putStr "Please input your name: "
name <- getLine
sayHello name
dogs

8F EJE TFWFSBM UIJOHT IFSF 0OF JT UIBU XF VTFE putStr JO


TUFBE PG putStrLn TP UIBU PVS JOQVU DPVME CF PO UIF TBNF MJOF BT
$)"15&3  #6*-%*/( 130+&$54 

PVS QSPNQU 8F BMTP JNQPSUFE GSPN System.IO TP UIBU XF DPVME


VTF hSetBuffering stdout BOE NoBuffering 5IBU MJOF PG DPEF JT
TP UIBU putStr JTOƊU CVƵFSFE EFGFSSFE
BOE QSJOUT JNNFEJBUFMZ
3FCVJME BOE SFSVO ZPVS QSPHSBN BOE JU TIPVME OPX XPSL MJLF
UIJT

$ stack exec hello


Please input your name: julie
Hi julie!
Who's a good puppy?!
YOU ARE!!!!!

:PV DBO USZ SFNPWJOH UIF NoBuffering MJOF UIBU XIPMF ƶSTU
MJOF
GSPN main BOE SFCVJMEJOH BOE SVOOJOH ZPVS QSPHSBN
UP TFF IPX JU DIBOHFT 8F XJMM CF VTJOH UIJT BT QBSU PG PVS
IBOHNBO HBNF JO B CJU CVU JU JTOƊU OFDFTTBSZ BU UIJT QPJOU UP
VOEFSTUBOE IPX UIF CVƵFSJOH GVODUJPOT XPSL JO BOZ EFUBJM

 EP TZOUBY BOE *0


8F UPVDIFE PO do OPUBUJPO B CJU BCPWF CVU XF XBOU UP FYQMBJO
B GFX NPSF UIJOHT BCPVU JU do CMPDLT BSF DPOWFOJFOU TZOUBDUJD
TVHBS UIBU BMMPX GPS TFRVFODJOH BDUJPOT CVU CFDBVTF UIFZ BSF
POMZ TZOUBDUJD TVHBS UIFZ BSF OPU TUSJDUMZ TQFBLJOH OFDFTTBSZ
5IFZ DBO NBLF CMPDLT PG DPEF NPSF SFBEBCMF BOE BMTP IJEF
UIF VOEFSMZJOH OFTUJOH BOE UIBU DBO IFMQ ZPV XSJUF FƵFDUGVM
$)"15&3  #6*-%*/( 130+&$54 

DPEF CFGPSF ZPV VOEFSTUBOE NPOBET BOE IO 4P ZPVƊMM TFF JU


B MPU JO UIJT DIBQUFS BOE JOEFFE ZPVƊMM TFF JU RVJUF B CJU JO
JEJPNBUJD )BTLFMM DPEF

5IF main FYFDVUBCMF JO B )BTLFMM QSPHSBN NVTU BMXBZT IBWF
UIF UZQF IO () 5IF do TZOUBY TQFDJƶDBMMZ BMMPXT VT UP TFRVFODF
NPOBEJD BDUJPOT Monad JT B UZQFDMBTT XFƊMM FYQMBJO JO HSFBU EFUBJM
JO B MBUFS DIBQUFS IFSF UIF JOTUBODF PG .POBE XF DBSF BCPVU JT
IO 5IBU JT XIZ main GVODUJPOT BSF PǒFO OPU BMXBZT
do CMPDLT
5IJT TZOUBY BMTP QSPWJEFT B XBZ PG OBNJOH WBMVFT SFUVSOFE
CZ NPOBEJD IO BDUJPOT TP UIBU UIFZ DBO CF VTFE BT JOQVUT UP
BDUJPOT UIBU IBQQFO MBUFS JO UIF QSPHSBN -FUƊT MPPL BU B WFSZ
TJNQMF do CMPDL BOE USZ UP HFU B GFFM GPS XIBUƊT IBQQFOJOH IFSF

main = do
-- [1]
x1 <- getLine
-- [2] [3] [4]
x2 <- getLine
-- [5]
return (x1 ++ x2)
-- [6] [7]

 do JOUSPEVDFT UIF CMPDL PG *0 BDUJPOT

 ԧ JT B WBSJBCMF SFQSFTFOUJOH UIF WBMVF PCUBJOFE GSPN UIF


*0 BDUJPO getLine
$)"15&3  #6*-%*/( 130+&$54 

 <- CJOET UIF WBSJBCMF PO UIF MFǒ UP UIF SFTVMU PG UIF *0


BDUJPO PO UIF SJHIU

 getLine IBT UIF UZQF IO String BOE UBLFT VTFS JOQVU PG B


TUSJOH WBMVF *O UIJT DBTF UIF TUSJOH UIF VTFS JOQVUT XJMM CF
UIF WBMVF CPVOE UP UIF ԧ OBNF

 ԧ JT B WBSJBCMF SFQSFTFOUJOH UIF WBMVF PCUBJOFE GSPN PVS


TFDPOE getLine "T BCPWF JU JT CPVOE UP UIBU WBMVF CZ UIF
<-

 return XJMM CF EJTDVTTFE JO NPSF EFUBJM TIPSUMZ CVU IFSF JU


JT UIF DPODMVEJOH BDUJPO PG PVS do CMPDL

 5IJT JT UIF WBMVF return XFMM SFUVSOT ƈ UIF DPOKVODUJPO PG


UIF UXP TUSJOHT XF PCUBJOFE GSPN PVS UXP getLine BDUJPOT

8IJMF <- JT VTFE UP CJOE B WBSJBCMF JU JT EJƵFSFOU GSPN PUIFS


NFUIPET XFƊWF TFFO JO FBSMJFS DIBQUFST GPS OBNJOH BOE CJOEJOH
WBSJBCMFT 5IJT BSSPX JT QBSU PG UIF TQFDJBM do TVHBS BOE TQFDJG
JDBMMZ CJOET B OBNF UP UIF Ԑ PG BO m a WBMVF XIFSF Ԝ JT TPNF
NPOBEJD TUSVDUVSF JO UIJT DBTF IO 5IF <- BMMPXT VT UP FYUSBDU
UIBU Ԑ BOE OBNF JU XJUIJO UIF MJNJUFE TDPQF PG UIF do CMPDL
BOE VTF UIBU OBNFE WBMVF BT BO JOQVU UP BOPUIFS FYQSFTTJPO
XJUIJO UIBU TBNF TDPQF &BDI BTTJHONFOU VTJOH <- DSFBUFT B
OFX WBSJBCMF SBUIFS UIBO NVUBUJOH BO FYJTUJOH WBSJBCMF CFDBVTF
EBUB JT JNNVUBCMF
$)"15&3  #6*-%*/( 130+&$54 

SFUVSO
5IJT GVODUJPO SFBMMZ EPFTOƊU EP B MPU CVU UIF QVSQPTF JU TFSWFT
JT JNQPSUBOU HJWFO UIF XBZ NPOBET BOE IO XPSL *U EPFT OPUI
JOH CVU SFUVSO B WBMVF CVU JU SFUVSOT B WBMVF JOTJEF NPOBEJD
TUSVDUVSF

Prelude> :t return
return :: Monad m => a -> m a

'PS PVS QVSQPTFT JO UIJT DIBQUFS return SFUVSOT B WBMVF JO


IO #FDBVTF UIF PCMJHBUPSZ UZQF PG main JT IO () UIF ƶOBM WBMVF
NVTU BMTP IBWF BO IO () UZQF BOE return HJWFT VT B XBZ UP BEE
OP FYUSB GVODUJPO FYDFQU QVUUJOH UIF ƶOBM WBMVF JO IO *G UIF
ƶOBM BDUJPO PG B do CMPDL JT return () UIBU NFBOT UIFSF JT OP
SFBM WBMVF UP SFUVSO BU UIF FOE PG QFSGPSNJOH UIF *0 BDUJPOT
CVU TJODF )BTLFMM QSPHSBNT DBOƊU SFUVSO MJUFSBMMZ OPUIJOH UIFZ
SFUVSO UIJT FNQUZ UVQMF DBMMFE VOJU TJNQMZ UP IBWF TPNFUIJOH
UP SFUVSO 5IBU FNQUZ UVQMF XJMM OPU QSJOU UP UIF TDSFFO JO UIF
3&1- CVU JUƊT UIFSF JO UIF VOEFSMZJOH SFQSFTFOUBUJPO
-FUƊT UBLF B MPPL BU return JO BDUJPO -FUƊT TBZ ZPV XBOU UP HFU
VTFS JOQVU PG UXP DIBSBDUFST BOE UFTU UIFN GPS FRVBMJUZ :PV
DBOƊU EP UIJT
$)"15&3  #6*-%*/( 130+&$54 

twoo :: IO Bool
twoo = do c <- getChar
c' <- getChar
c == c'

5SZ JU BOE TFF XIBU ZPVS UZQF FSSPS MPPLT MJLF *U TIPVME
UFMM ZPV UIBU JU DBOƊU NBUDI UIF FYQFDUFE UZQF IO Bool XJUI UIF
BDUVBM UZQF PG c == c' XIJDI JT #PPM 4P PVS ƶOBM MJOF OFFET
UP SFUVSO UIBU Bool WBMVF JO IO

twoo :: IO Bool
twoo = do c <- getChar
c' <- getChar
return (c == c')

8F QVU UIF Bool WBMVF JOUP IO CZ VTJOH return $PPM )PX


BCPVU JG XF IBWF DBTFT XIFSF XF XBOU UP SFUVSO OPUIJOH 8FƊMM
SFVTF UIF TBNF CBTJD DPEF GSPN BCPWF CVU NBLF BO if-then-else
XJUIJO PVS do CMPDL

main :: IO ()
main = do c <- getChar
c' <- getChar
if c == c'
then putStrLn "True"
else return ()
$)"15&3  #6*-%*/( 130+&$54 

8IBU IBQQFOT XIFO UIF UXP JOQVU DIBSBDUFST BSF FRVBM


8IBU IBQQFOT XIFO UIFZ BSFOƊU
4PNF QFPQMF IBWF OPUFE UIBU do TZOUBY NBLFT JU GFFM MJLF
ZPVƊSF EPJOH JNQFSBUJWF QSPHSBNNJOH JO )BTLFMM *UƊT JNQPS
UBOU UP OPUF UIBU UIJT FƵFDUGVM JNQFSBUJWF TUZMF SFRVJSFT IBWJOH
IO JO PVS SFTVMU UZQF 8F DBOOPU QFSGPSN FƵFDUT XJUIPVU FWJ
EFODF PG IBWJOH EPOF TP JO UIF UZQF do JT POMZ TZOUBDUJD TVHBS
CVU UIF NPOBEJD TZOUBY XFƊMM DPWFS JO B MBUFS DIBQUFS XPSLT JO
B TJNJMBS XBZ GPS NPOBET PUIFS UIBO *0

%P OPUBUJPO DPOTJEFSFE IBSNGVM +VTU LJEEJOH #VU TPNF


UJNFT FOUIVTJBTUJD QSPHSBNNFST PWFSVTF do CMPDLT *U JT OPU
OFDFTTBSZ BOE DPOTJEFSFE CBE TUZMF UP VTF do JO TJOHMFMJOF
FYQSFTTJPOT :PV XJMM FWFOUVBMMZ MFBSO UP VTF >>= JO TJOHMF
MJOF FYQSFTTJPOT JOTUFBE PG do UIFSFƊT BO FYBNQMF PG UIBU JO
UIJT DIBQUFS
 4JNJMBSMZ JU JT VOOFDFTTBSZ UP VTF do XJUI GVOD
UJPOT MJLF putStrLn BOE print UIBU BMSFBEZ IBWF UIF FƵFDUT CBLFE
JO *O UIF GVODUJPO BCPWF XF DPVME IBWF QVU do JO GSPOU PG
CPUI putStrLn BOE return BOE JU XPVME IBWF XPSLFE UIF TBNF
CVU UIJOHT HFU NFTTZ BOE UIF )BTLFMM OJOKBT XJMM DPNF BOE CF
TFWFSFMZ EJTBQQPJOUFE JO ZPV

 )BOHNBO HBNF


/PX XFƊSF SFBEZ UP CVJME B HBNF .BLF B EJSFDUPSZ GPS ZPVS
HBNF DIBOHF TP ZPVƊSF XPSLJOH XJUIJO UIBU EJSFDUPSZ BOE
$)"15&3  #6*-%*/( 130+&$54 

ƶSF VQ UIF 4UBDL 8FƊMM VTF 4UBDLƊT new DPNNBOE UP DSFBUF UIJT
QSPKFDU

$ stack new hangman simple

:PV OFFE B words ƶMF GPS HFUUJOH XPSET GSPN .PTU 6OJY
CBTFE PQFSBUJOH TZTUFNT XJMM IBWF B XPSET MJTU MPDBUFE BU B
EJSFDUPSZ MJLF UIF GPMMPXJOH

$ ls /usr/share/dict/
american-english british-english
cracklib-small README.select-wordlist
words words.pre-dictionaries-common

*O UIJT DBTF XFƊMM VTF UIF words XPSE MJTU XIJDI TIPVME CF
ZPVS PQFSBUJOH TZTUFNƊT EFGBVMU :PV NBZ IBWF POF UIBU JT
EJƵFSFOUMZ MPDBUFE PS ZPV NBZ OFFE UP EPXOMPBE POF 8F
QVU JU JO UIF XPSLJOH EJSFDUPSZ BU data/dict.txt

$ tree .
.
├── LICENSE
├── Setup.hs
├── data
│ └── dict.txt
├── hangman.cabal
├── src
$)"15&3  #6*-%*/( 130+&$54 

│ └── Main.hs
└── stack.yaml

:PV IBWFOƊU DSFBUFE UIBU src EJSFDUPSZ ZFU ƈ ZPV XJMM TPPO
5IF ƶMF XBT OFXMJOF TFQBSBUFE BOE TP MPPLFE MJLF

$ head data/dict.txt
A
a
aa
aal
aalii
aam
Aani
aardvark
aardwolf
Aaron

/PX FEJU UIF .cabal ƶMF BT GPMMPXT

name: hangman
version: 0.1.0.0
synopsis: Playing Hangman
homepage: Chris N Julie
license: BSD3
license-file: LICENSE
author: Chris Allen and Julie Moronuki
$)"15&3  #6*-%*/( 130+&$54 

maintainer: haskellbook.com
category: Game
build-type: Simple
extra-source-files: data/dict.txt
cabal-version: >=1.10
executable hangman
main-is: Main.hs
hs-source-dirs: src
build-depends: base >=4.7 && <5
, random
, split
default-language: Haskell2010

5IF JNQPSUBOU CJU IFSF JT UIBU XF VTFE UXP MJCSBSJFT SBOEPN


BOE TQMJU /PSNBMMZ ZPVƊE EP WFSTJPO SBOHFT GPS ZPVS EFQFO
EFODJFT MJLF ZPV TFF XJUI CBTF CVU XF MFǒ UIF WFSTJPOT PG SBOEPN
BOE TQMJU VOBTTJHOFE CFDBVTF UIFZ EP OPU DIBOHF NVDI 5IF
QSJNBSZ BOE POMZ TPVSDF ƶMF XBT JO src/Main.hs
$)"15&3  #6*-%*/( 130+&$54 

 4UFQ 0OF *NQPSUJOH NPEVMFT


-- src/Main.hs

module Main where

import Control.Monad (forever) -- [1]


import Data.Char (toLower) -- [2]
import Data.Maybe (isJust) -- [3]
import Data.List (intersperse) -- [4]
import System.Exit (exitSuccess) -- [5]
import System.Random (randomRIO) -- [6]

)FSF UIF JNQPSUT BSF FOVNFSBUFE JO UIF TPVSDF DPEF 'PS


ZPVS WFSTJPO PG UIJT QSPKFDU ZPV EPOƊU OFFE UP BEE UIF FOVNFS
BUJOH DPNNFOUT "MM NPEVMFT MJTUFE CFMPX BSF QBSU PG UIF NBJO
CBTF MJCSBSZ UIBU DPNFT XJUI ZPVS ()$ JOTUBMM VOMFTT PUIFSXJTF
OPUFE

 8FƊSF VTJOH forever GSPN $POUSPM.POBE UP NBLF BO JOƶ


OJUF MPPQ " DPVQMF QPJOUT UP OPUF

B
:PV EPOƊU IBWF UP VTF forever UP EP UIJT CVU XFƊSF HPJOH
UP
C
:PV BSF OPU FYQFDUFE UP VOEFSTUBOE XIBU JU EPFT PS
IPX JU XPSLT FYBDUMZ #BTJDBMMZ JU BMMPXT VT UP FYFDVUF
$)"15&3  #6*-%*/( 130+&$54 

B GVODUJPO PWFS BOE PWFS BHBJO JOƶOJUFMZ PS VOUJM


XF DBVTF UIF QSPHSBN UP FYJU PS GBJM JOTUFBE PG KVTU
FWBMVBUJOH PODF BOE UIFO TUPQQJOH

 8F XJMM VTF toLower GSPN Data.Char UP DPOWFSU BMM DIBSBDUFST


PG PVS TUSJOH UP MPXFSDBTF

Prelude> import Data.Char (toLower)


Prelude> toLower 'A'
'a'

#F BXBSF UIBU JG ZPV QBTT B DIBSBDUFS UIBU EPFTOƊU IBWF B


TFOTJCMF MPXFSDBTF toLower XJMM LJDL UIF TBNF DIBSBDUFS
CBDL PVU

Prelude> toLower ':'


':'

 8F XJMM VTF isJust GSPN Data.Maybe UP EFUFSNJOF JG FWFSZ


DIBSBDUFS JO PVS QV[[MF IBT CFFO EJTDPWFSFE BMSFBEZ PS
OPU

Prelude> import Data.Maybe (isJust)


Prelude> isJust Nothing
False
Prelude> isJust (Just 10)
True
$)"15&3  #6*-%*/( 130+&$54 

8F XJMM DPNCJOF UIJT XJUI all B TUBOEBSE GVODUJPO JO


UIF 1SFMVEF )FSF all JT B GVODUJPO XIJDI BOTXFST UIF
RVFTUJPO ƌHJWFO B GVODUJPO UIBU XJMM SFUVSO 5SVF PS 'BMTF
GPS FBDI FMFNFOU EPFT JU SFUVSO 5SVF GPS BMM PG UIFN ƍ

Prelude> all even [2, 4, 6]


True
Prelude> all even [2, 4, 7]
False
Prelude> all isJust [Just 'd', Nothing, Just 'g']
False
Prelude> all isJust [Just 'd', Just 'o', Just 'g']
True

5IF GVODUJPO all IBT UIF UZQF

Foldable t => (a -> Bool) -> t a -> Bool

8F IBWFOƊU FYQMBJOFE UIF Foldable UZQFDMBTT 'PS ZPVS


QVSQPTFT ZPV DBO BTTVNF JUƊT B TFU PG PQFSBUJPOT GPS UZQFT
UIBU DBO CF GPMEFE JO B NBOOFS DPODFQUVBMMZ TJNJMBS UP
UIF MJTU UZQF CVU XIJDI EPOƊU OFDFTTBSJMZ DPOUBJO NPSF UIBO
POF WBMVF PS BOZ WBMVFT BU BMM
UIF XBZ B MJTU PS TJNJMBS
EBUBUZQF EPFT 8F DBO NBLF UIF UZQF NPSF TQFDJƶD CZ
BTTFSUJOH B UZQF TJHOBUVSF MJLF TP

Prelude> :t all :: (a -> Bool) -> [a] -> Bool


$)"15&3  #6*-%*/( 130+&$54 

all :: (a -> Bool) -> [a] -> Bool

5IJT XJMM XPSL GPS BOZ UZQF XIJDI IBT B Foldable JOTUBODF

Prelude> :t all :: (a -> Bool) -> Maybe a -> Bool


all :: (a -> Bool) -> Maybe a -> Bool

-- note the type variables used and


-- experiment independently
Prelude> :t all :: (a -> Bool) -> Either b a -> Bool
all :: (a -> Bool) -> Either b a -> Bool

#VU JU XJMM OPU XPSL JG UIF EBUBUZQF EPFTOƊU IBWF BO JOTUBODF


PG Foldable

Prelude> :t all :: (a -> Bool) -> (b -> a) -> Bool

No instance for (Foldable ((->) b1)) arising


from a use of ‘all’

In the expression:
all :: (a -> Bool) -> (b -> a) -> Bool

 8F VTF intersperse GSPN Data.List UPƒJOUFSTQFSTF FMFNFOUT


JO B MJTU *O UIJT DBTF XFƊSF QVUUJOH TQBDFT CFUXFFO UIF
$)"15&3  #6*-%*/( 130+&$54 

DIBSBDUFST HVFTTFE TP GBS CZ UIF QMBZFS :PV NBZ SFNFN


CFS XF VTFE intersperse CBDL JO UIF 3FDVSTJPO DIBQUFS UP
QVU IZQIFOT JO PVS /VNCFST *OUP 8PSET FYFSDJTF

Prelude> import Data.List (intersperse)


Prelude> intersperse ' ' "Blah"
"B l a h"

$POWFOJFOUMZ UIF UZQF PG intersperse TBZT OPUIJOH BCPVU


DIBSBDUFST PS TUSJOHT TP XF DBO VTF JU XJUI MJTUT DPOUBJOJOH
FMFNFOUT PG BOZ UZQF

Prelude> :t intersperse
intersperse :: a -> [a] -> [a]

Prelude> intersperse 0 [1, 1, 1]


[1,0,1,0,1]

 8F VTF exitSuccess GSPN System.Exit UP FYJU TVDDFTTGVMMZ ƈ


OP FSSPST XFƊSF TJNQMZ EPOF 8F JOEJDBUF XIFUIFS JU XBT
B TVDDFTT PS OPU TP PVS PQFSBUJOH TZTUFN LOPXT XIFUIFS
BO FSSPS PDDVSSFE /PUF UIBU JG ZPV FWBMVBUF exitSuccess JO
UIF 3&1- JUƊMM KVTU SFQPSU UIBU BO FYDFQUJPO PDDVSSFE *O B
OPSNBM SVOOJOH QSPHSBN UIBU EPFTOƊU DBUDI UIF FYDFQUJPO
JUƊMM FOE ZPVS XIPMF QSPHSBN
$)"15&3  #6*-%*/( 130+&$54 

 8F VTF randomRIO GSPN System.Random UP TFMFDU B XPSE GSPN


PVS EJDUJPOBSZ BU SBOEPN System.Random JT JO UIF MJCSBSZ
SBOEPN 0ODF BHBJO ZPVƊMM OFFE UP IBWF UIF MJCSBSZ JO
TDPQF GPS ZPVS 3&1- UP CF BCMF UP MPBE JU 0ODF JUƊT JO
TDPQF XF DBO VTF randomRIO UP HFU B SBOEPN OVNCFS :PV
DBO TFF GSPN UIF UZQF TJHOBUVSF UIBU JU UBLFT B UVQMF BT BO
BSHVNFOU CVU JU VTFT UIF UVQMF BT B SBOHF GSPN XIJDI UP
TFMFDU B SBOEPN JUFN

Prelude> import System.Random


Prelude System.Random> :t randomRIO
randomRIO :: Random a => (a, a) -> IO a
Prelude System.Random> randomRIO (0, 5)
4
Prelude System.Random> randomRIO (1, 100)
71
Prelude System.Random> randomRIO (1, 100)
12

8F XJMM MBUFS VTF UIJT SBOEPN OVNCFS HFOFSBUJPO UP QSP


EVDF B SBOEPN JOEFY PG B XPSE MJTU UP QSPWJEF B NFBOT PG
TFMFDUJOH SBOEPN XPSET GPS PVS QV[[MF
$)"15&3  #6*-%*/( 130+&$54 

 4UFQ 5XP (FOFSBUJOH B XPSE MJTU


'PS DMBSJUZƊT TBLF XFƊSF VTJOH B UZQF TZOPOZN UP EFDMBSF XIBU
XF NFBO CZ [String] JO PVS UZQFT -BUFS XFƊMM TIPX ZPV B
WFSTJPO UIBUƊT FWFO NPSF FYQMJDJU VTJOH OFXUZQF 8F BMTP VTF
do TZOUBY UP SFBE UIF DPOUFOUT PG PVS EJDUJPOBSZ JOUP B WBSJBCMF
OBNFE dict 8F VTF UIF lines GVODUJPO UP TQMJU PVS CJH CMPC
TUSJOH XF SFBE GSPN UIF ƶMF JOUP B MJTU PG TUSJOH WBMVFT FBDI
SFQSFTFOUJOH B TJOHMF MJOF &BDI MJOF JT B TJOHMF XPSE TP PVS
SFTVMU JT UIF WordList

type WordList = [String]

allWords :: IO WordList
allWords = do
dict <- readFile "data/dict.txt"
return (lines dict)

-FUƊT UBLF B NPNFOU UP MPPL BU lines XIJDI TQMJUT TUSJOHT BU


UIF OFXMJOF NBSLT BOE SFUVSOT B MJTU PG TUSJOHT

Prelude> lines "aardvark\naaron"


["aardvark","aaron"]
Prelude> length $ lines "aardvark\naaron"
2
Prelude> length $ lines "aardvark\naaron\nwoot"
3
$)"15&3  #6*-%*/( 130+&$54 

Prelude> lines "aardvark aaron"


["aardvark aaron"]
Prelude> length $ lines "aardvark aaron"
1

/PUF UIBU UIJT EPFT TPNFUIJOH TJNJMBS CVU EJƵFSFOU GSPN


words XIJDI TQMJUT CZ TQBDFT PTUFOTJCMZ CFUXFFO XPSET
BOE
OFXMJOFT

Prelude> words "aardvark aaron"


["aardvark","aaron"]
Prelude> words "aardvark\naaron"
["aardvark","aaron"]

5IF OFYU QBSU PG CVJMEJOH PVS XPSE MJTU GPS PVS QV[[MF JT UP
TFU VQQFS BOE MPXFS CPVOET GPS UIF TJ[F PG XPSET XFƊMM VTF JO
UIF QV[[MFT 'FFM GSFF UP DIBOHF UIFN JG ZPV XBOU

minWordLength :: Int
minWordLength = 5

maxWordLength :: Int
maxWordLength = 9

5IF OFYU UIJOH XFƊSF HPJOH UP EP JT UBLF UIF PVUQVU PG


allWords BOE ƶMUFS JU UP ƶU UIF MFOHUI DSJUFSJB XF EFƶOFE BCPWF
5IBU XJMM HJWF VT B TIPSUFS MJTU PG XPSET UP VTF JO UIF QV[[MFT
$)"15&3  #6*-%*/( 130+&$54 

gameWords :: IO WordList
gameWords = do
aw <- allWords
return (filter gameLength aw)
where gameLength w =
let l = length (w :: String)
in l > minWordLength && l < maxWordLength

8F OFYU OFFE UP XSJUF B QBJS PG GVODUJPOT UIBU XJMM QVMM B


SBOEPN XPSE PVU PG PVS XPSE MJTU GPS VT TP UIBU UIF QV[[MF
QMBZFS EPFTOƊU LOPX XIBU UIF XPSE XJMM CF 8FƊSF HPJOH UP VTF
UIF randomRIO GVODUJPO XF NFOUJPOFE BCPWF UP GBDJMJUBUF UIBU
8FƊMM QBTT randomRIO B UVQMF PG [FSP UIF ƶSTU JOEFYFE QPTJUJPO
JO PVS XPSE MJTU
BOE UIF OVNCFS UIBU JT UIF MFOHUI PG PVS XPSE
MJTU NJOVT POF 8IZ NJOVT POF
8F IBWF UP TVCUSBDU POF GSPN UIF MFOHUI PG UIF XPSE MJTU
JO PSEFS UP JOEFY JU CFDBVTF length TUBSUT DPVOUJOH GSPN  CVU
BO JOEFY PG UIF MJTU TUBSUT GSPN  " MJTU PG MFOHUI  EPFT OPU
IBWF B NFNCFS JOEFYFE BU QPTJUJPO  ƈ JU IBT JOIBCJUBOUT BU
QPTJUJPOT  JOTUFBE

Prelude> [1..5] !! 4
5
Prelude> [1..5] !! 5
*** Exception: Prelude.(!!): index too large
$)"15&3  #6*-%*/( 130+&$54 

*O PSEFS UP HFU UIF MBTU WBMVF JO UIF MJTU UIFO XF NVTU BTL
GPS UIF NFNCFS JO UIF QPTJUJPO PG UIF MFOHUI PG UIF MJTU NJOVT
POF

Prelude> let myList = [1..5]


Prelude> length myList
5
Prelude> myList !! length myList
*** Exception: Prelude.!!: index too large

Prelude> myList !! (length myList - 1)


5

5IF OFYU UXP GVODUJPOT XPSL UPHFUIFS UP QVMM B SBOEPN


XPSE PVU PG UIF gameWords MJTU XF IBE DSFBUFE BCPWF 3PVHIMZ
TQFBLJOH randomWord HFOFSBUFT B SBOEPN JOEFY OVNCFS CBTFE
PO UIF MFOHUI PG B XPSE MJTU wl BOE UIFO TFMFDUT UIF NFNCFS
PG UIBU MJTU UIBU JT BU UIBU JOEFYFE QPTJUJPO BOE SFUVSOT BO IO
String (JWFO XIBU ZPV LOPX BCPVU randomRIO BOE JOEFYJOH
ZPV TIPVME CF BCMF UP TVQQMZ UIF UVQMF BSHVNFOU UP randomRIO
ZPVSTFMG

randomWord :: WordList -> IO String


randomWord wl = do
randomIndex <- randomRIO ( , )
-- ^^^ you need to fill this part in
return $ wl !! randomIndex
$)"15&3  #6*-%*/( 130+&$54 

5IF TFDPOE GVODUJPO randomWord' CJOET UIF gameWords MJTU UP


UIF randomWord GVODUJPO TP UIBU UIF SBOEPN XPSE XFƊSF HFUUJOH
JT GSPN UIBU MJTU 8FƊSF HPJOH UP EFMBZ B GVMM EJTDVTTJPO PG UIF >>=
PQFSBUPS LOPXO BT ƌCJOEƍ VOUJM XF HFU UP UIF .POBET DIBQUFS
'PS OPX XF DBO TBZ UIBU BT XF TBJE BCPVU do TZOUBY CJOE BMMPXT
VT UP TFRVFOUJBMMZ DPNQPTF BDUJPOT TVDI UIBU B WBMVF HFOFSBUFE
CZ UIF ƶSTU CFDPNFT BO BSHVNFOU UP UIF TFDPOE

randomWord' :: IO String
randomWord' = gameWords >>= randomWord

/PX UIBU XF IBWF B XPSE MJTU XF UVSO PVS BUUFOUJPO UP UIF


CVJMEJOH PG BO JOUFSBDUJWF HBNF VTJOH JU

 4UFQ 5ISFF .BLJOH B QV[[MF


0VS OFYU TUFQ JT UP GPSNVMBUF UIF DPSF HBNF QMBZ 8F OFFE B
XBZ UP IJEF UIF XPSE GSPN UIF QMBZFS XIJMF HJWJOH UIFN BO
JOEJDBUJPO PG IPX NBOZ MFUUFST JU IBT
BOE DSFBUF B NFBOT PG
BTLJOH GPS MFUUFS HVFTTFT EFUFSNJOJOH JG UIF HVFTTFE MFUUFS JT
JO UIF XPSE QVUUJOH JU JO UIF XPSE JG JU JT BOE QVUUJOH JU JOUP
BO ƌBMSFBEZ HVFTTFEƍ MJTU JG JUƊT OPU BOE EFUFSNJOJOH XIFO UIF
HBNF FOET
8F TUBSU XJUI B EBUBUZQF GPS PVS QV[[MF 5IF QV[[MF JT B
QSPEVDU PG B String B MJTU PG Maybe Char BOE B MJTU PG Char
$)"15&3  #6*-%*/( 130+&$54 

data Puzzle = Puzzle String [Maybe Char] [Char]


-- [1] [2] [3]

 UIF XPSE XFƊSF USZJOH UP HVFTT

 UIF DIBSBDUFST XFƊWF ƶMMFE JO TP GBS

 UIF MFUUFST XFƊWF HVFTTFE TP GBS

/FYU XFƊSF HPJOH UP XSJUF BO JOTUBODF PG UIF UZQFDMBTT Show


GPS PVS EBUBUZQF Puzzle :PV NBZ SFDBMM UIBU show BMMPXT VT UP
QSJOU IVNBOSFBEBCMF TUSJOHZ UIJOHT UP UIF TDSFFO XIJDI JT
PCWJPVTMZ TPNFUIJOH XF IBWF UP EP UP JOUFSBDU XJUI PVS HBNF
#VU XF XBOU JU UP QSJOU PVS QV[[MF B DFSUBJO XBZ TP XF EFƶOF
UIJT JOTUBODF
/PUJDF IPX UIF BSHVNFOU UP show MJOFT VQ XJUI PVS EBUBUZQF
EFƶOJUJPO BCPWF /PX discovered SFGFST UP PVS MJTU PG Maybe Char
BOE guessed JT XIBU XFƊWF OBNFE PVS MJTU PG Char CVU XFƊWF
EPOF OPUIJOH XJUI UIF String JUTFMG

instance Show Puzzle where


show (Puzzle _ discovered guessed) =
(intersperse ' ' $ fmap renderPuzzleChar discovered)
++ " Guessed so far: " ++ guessed

5IJT JT HPJOH UP TIPX VT UXP UIJOHT BT QBSU PG PVS QV[[MF


UIF MJTU PG Maybe Char XIJDI JT UIF TUSJOH PG DIBSBDUFST XF IBWF
DPSSFDUMZ HVFTTFE BOE UIF SFTU PG UIF DIBSBDUFST PG UIF QV[[MF
$)"15&3  #6*-%*/( 130+&$54 

XPSE SFQSFTFOUFE CZ VOEFSTDPSFT JOUFSTQFSTFE XJUI TQBDFT


BOE B MJTU PG Char UIBU SFNJOET VT PG XIJDI DIBSBDUFST XFƊWF
BMSFBEZ HVFTTFE 8FƊMM UBML BCPVU renderPuzzleChar CFMPX
'JSTU XFƊSF HPJOH UP XSJUF B GVODUJPO UIBU XJMM UBLF PVS QV[[MF
XPSE BOE UVSO JU JOUP B MJTU PG Nothing 5IJT JT UIF ƶSTU TUFQ JO
IJEJOH UIF XPSE GSPN UIF QMBZFS 8FƊSF HPJOH UP BTL ZPV UP
XSJUF UIJT POF ZPVSTFMG VTJOH UIF GPMMPXJOH JOGPSNBUJPO

Ƒ 8FƊWF HJWFO ZPV B UZQF TJHOBUVSF :PVS ƶSTU BSHVNFOU JT B


String XIJDI XJMM CF UIF XPSE UIBU JT JO QMBZ *U XJMM SFUVSO
B WBMVF PG UZQF Puzzle 3FNFNCFS UIBU UIF Puzzle UZQF JT B
QSPEVDU PG UISFF UIJOHT

Ƒ :PVS ƶSTU WBMVF JO UIF PVUQVU XJMM CF UIF TBNF TUSJOH BT


UIF BSHVNFOU UP UIF GVODUJPO

Ƒ 5IF TFDPOE WBMVF XJMM CF UIF SFTVMU PG NBQQJOH B GVODUJPO


PWFS UIBU String BSHVNFOU $POTJEFS VTJOH const JO UIF
NBQQFE GVODUJPO BT JU XJMM BMXBZT SFUVSO JUT ƶSTU BSHVNFOU
OP NBUUFS XIBU JUT TFDPOE BSHVNFOU JT

Ƒ 'PS QVSQPTFT PG UIJT GVODUJPO UIF ƶOBM BSHVNFOU PG Puzzle


JT BO FNQUZ MJTU

(P GPS JU

freshPuzzle :: String -> Puzzle


freshPuzzle = undefined
$)"15&3  #6*-%*/( 130+&$54 

/PX XF OFFE B GVODUJPO UIBU MPPLT BU UIF Puzzle String BOE


EFUFSNJOFT XIFUIFS UIF DIBSBDUFS ZPV HVFTTFE JT BO FMFNFOU
PG UIBU TUSJOH )FSF BSF TPNF IJOUT

Ƒ 5IJT JT HPJOH UP OFFE UXP BSHVNFOUT BOE POF PG UIPTF


JT PG UZQF Puzzle XIJDI JT B QSPEVDU PG  UZQFT #VU GPS
UIF QVSQPTF PG UIJT GVODUJPO XF POMZ DBSF BCPVU UIF ƶSTU
BSHVNFOU UP Puzzle

Ƒ 8F DBO VTF VOEFSTDPSFT UP TJHOBM UIBU UIFSF BSF WBMVFT


XF EPOƊU DBSF BCPVU BOE UFMM UIF GVODUJPO UP JHOPSF UIFN
8IFUIFS ZPV VTF VOEFSTDPSFT UP SFQSFTFOU UIF BSHVNFOUT
ZPV EPOƊU DBSF BCPVU PS HP BIFBE BOE QVU UIF OBNFT PG
UIPTF JO XPOƊU BƵFDU UIF SFTVMU PG UIF GVODUJPO *U EPFT
IPXFWFS LFFQ ZPVS DPEF B CJU DMFBOFS BOE FBTJFS UP SFBE
CZ FYQMJDJUMZ TJHOBMJOH XIJDI BSHVNFOUT ZPV DBSF BCPVU
JO B HJWFO GVODUJPO

Ƒ 5IF TUBOEBSE GVODUJPO elem XPSLT MJLF UIJT

Prelude> :t elem
elem :: Eq a => a -> [a] -> Bool
Prelude> elem 'a' "julie"
False
Prelude> elem 3 [1..5]
True

4P IFSF ZPV HP


$)"15&3  #6*-%*/( 130+&$54 

charInWord :: Puzzle -> Char -> Bool


charInWord = undefined

5IF OFYU GVODUJPO JT WFSZ TJNJMBS UP UIF POF ZPV KVTU XSPUF
CVU UIJT UJNF XF EPOƊU DBSF JG UIF Char JT QBSU PG UIF String
BSHVNFOU ƈ UIJT UJNF XF XBOU UP DIFDL BOE TFF JG JU JT BO
FMFNFOU PG UIF guessed MJTU
:PVƊWF UPUBMMZ HPU UIJT

alreadyGuessed :: Puzzle -> Char -> Bool


alreadyGuessed = undefined

0, TP GBS XF IBWF XBZT UP DIPPTF B XPSE UIBU XFƊSF USZJOH


UP HVFTT BOE EFUFSNJOF JG B HVFTTFE DIBSBDUFS JT QBSU PG UIBU
XPSE PS OPU #VU XF OFFE B XBZ UP IJEF UIF SFTU PG UIF XPSE
GSPN UIF QMBZFS XIJMF UIFZƊSF HVFTTJOH $PNQVUFST BSF B CJU
EVNC BǒFS BMM BOE DBOƊU ƶHVSF PVU IPX UP LFFQ TFDSFUT PO
UIFJS PXO #BDL XIFO XF EFƶOFE PVS Show JOTUBODF GPS UIJT
QV[[MF XF GNBQQFE B GVODUJPO DBMMFE renderPuzzleChar PWFS
PVS TFDPOE Puzzle BSHVNFOU -FUƊT XPSL PO UIBU GVODUJPO OFYU
5IF HPBM IFSF JT UP VTF Maybe UP QFSNJU UXP EJƵFSFOU PVU
DPNFT *U XJMM CF NBQQFE PWFS B TUSJOH JO UIF UZQFDMBTT JOTUBODF
TP UIJT GVODUJPO XPSLT PO POMZ POF DIBSBDUFS BU B UJNF *G UIBU
DIBSBDUFS IBT OPU CFFO DPSSFDUMZ HVFTTFE ZFU JUƊT B Nothing WBMVF
BOE TIPVME BQQFBS PO UIF TDSFFO BT BO VOEFSTDPSF *G UIF DIBS
BDUFS IBT CFFO HVFTTFE XF XBOU UP EJTQMBZ UIBU DIBSBDUFS TP
UIF QMBZFS DBO TFF XIJDI QPTJUJPOT UIFZƊWF DPSSFDUMZ ƶMMFE
$)"15&3  #6*-%*/( 130+&$54 

*Main> renderPuzzleChar Nothing


'_'
*Main> renderPuzzleChar (Just 'c')
'c'
*Main> let n = Nothing
*Main> let daturr = [n, Just 'h', n, Just 'e', n]
*Main> fmap renderPuzzleChar daturr
"_h_e_"

:PVS UVSO 3FNFNCFS ZPV EPOƊU OFFE UP EP UIF NBQQJOH


QBSU PG JU IFSF

renderPuzzleChar :: Maybe Char -> Char


renderPuzzleChar = undefined

5IF OFYU CJU JT B UPVDI USJDLZ 5IF QPJOU JT UP JOTFSU B DPS


SFDUMZ HVFTTFE DIBSBDUFS JOUP UIF TUSJOH "MUIPVHI OPOF PG UIF
DPNQPOFOUT IFSF BSF OFX UP ZPV UIFZƊSF QVU UPHFUIFS JO B
TPNFXIBU EFOTF NBOOFS TP XFƊSF HPJOH UP VOQBDL JU PCWJ
PVTMZ XIFO ZPV UZQF UIJT JOUP ZPVS PXO ƶMF ZPV EP OPU OFFE
UP BEE UIF FOVNFSBUJPOT

$)"15&3  #6*-%*/( 130+&$54 

fillInCharacter :: Puzzle -> Char -> Puzzle


fillInCharacter (Puzzle word filledInSoFar s) c =
-- [1] [2]
Puzzle word newFilledInSoFar (c : s)
-- [ 3 ]
where zipper guessed wordChar guessChar =
-- [4] [5] [6] [7]
if wordChar == guessed
then Just wordChar
else guessChar
-- [ 8 ]
newFilledInSoFar =
-- [9]
zipWith (zipper c) word filledInSoFar
-- [ 10 ]

 5IF ƶSTU BSHVNFOU JT PVS Puzzle XJUI JUT UISFF BSHVNFOUT


XJUI T SFQSFTFOUJOH UIF MJTU PG DIBSBDUFST BMSFBEZ HVFTTFE

 5IF D JT PVS Char BSHVNFOU BOE JT UIF DIBSBDUFS UIF QMBZFS


HVFTTFE PO UIJT UVSO

 0VS SFTVMU JT UIF Puzzle XJUI UIF filledInSoFar SFQMBDFE CZ


newFilledInSoFar UIF D DPOTFE POUP UIF GSPOU PG UIF T MJTU

 zipper JT B DPNCJOJOH GVODUJPO GPS EFDJEJOH IPX UP IBOEMF


UIF DIBSBDUFS JO UIF XPSE XIBUƊT CFFO HVFTTFE BMSFBEZ
$)"15&3  #6*-%*/( 130+&$54 

BOE UIF DIBSBDUFS UIBU XBT KVTU HVFTTFE *G UIF DVSSFOU


DIBSBDUFS JO UIF XPSE JT FRVBM UP XIBU UIF QMBZFS HVFTTFE
UIFO XF HP BIFBE BOE SFUVSO Just wordChar UP ƶMM JO UIBU
TQPU JO UIF QV[[MF 0UIFSXJTF XF KVTU LJDL UIF guessChar
CBDL PVU 8F LJDL guessChar CBDL PVU CFDBVTF JU NJHIU
FJUIFS CF B QSFWJPVTMZ DPSSFDUMZ HVFTTFE DIBSBDUFS PS B
Nothing UIBU IBT OPU CFFO HVFTTFE DPSSFDUMZ UIJT UJNF OPS
JO UIF QBTU

 guessed JT UIF DIBSBDUFS UIFZ HVFTTFE

 wordChar JT UIF DIBSBDUFST JO UIF QV[[MF XPSE ƈ OPU UIF


POFT UIFZƊWF HVFTTFE PS OPU HVFTTFE CVU UIF DIBSBDUFST
JO UIF XPSE UIBU UIFZƊSF TVQQPTFE UP CF HVFTTJOH

 guessChar JT UIF MJTU UIBU LFFQT USBDL PG UIF DIBSBDUFST UIF


QMBZFS IBT HVFTTFE TP GBS

 5IJT if-then-else FYQSFTTJPO DIFDLT UP TFF JG UIF HVFTTFE


DIBSBDUFS JT POF PG UIF XPSE DIBSBDUFST *G JU JT JU XSBQT JU
JO B Just CFDBVTF PVS QV[[MF XPSE JT B MJTU PG Maybe WBMVFT
0UIFSXJTF JU JT B HVFTTFE DIBSBDUFS CVU EPFT OPU CFMPOH
JO UIF XPSE

 newFilledInSoFar JT UIF OFX TUBUF PG UIF QV[[MF XIJDI VTFT


zipWith BOE UIF zipper DPNCJOJOH GVODUJPO UP ƶMM JO DIBS
BDUFST JO UIF QV[[MF 5IF zipper GVODUJPO JT ƶSTU BQQMJFE UP
UIF DIBSBDUFS UIF QMBZFS KVTU HVFTTFE CFDBVTF UIBU EPFTOƊU
$)"15&3  #6*-%*/( 130+&$54 

DIBOHF 5IFO JUƊT [JQQFE BDSPTT UXP MJTUT 0OF MJTU JT word
XIJDI JT UIF XPSE UIF VTFS JT USZJOH UP HVFTT 5IF TFDPOE
MJTU filledInSoFar JT UIF QV[[MF TUBUF XFƊSF TUBSUJOH XJUI PG
UZQF [Maybe Char] 5IBUƊT UFMMJOH VT XIJDI DIBSBDUFST JO
word IBWF CFFO HVFTTFE

 /PX XFƊSF HPJOH UP NBLF PVS newFilledInSoFar CZ VTJOH


zipWith :PV NBZ SFNFNCFS UIJT GSPN UIF -JTUT DIBQUFS
*UƊT HPJOH UP [JQ UIF word XJUI UIF filledInSoFar WBMVFT XIJMF
BQQMZJOH UIF zipper GVODUJPO GSPN KVTU BCPWF JU UP UIF
WBMVFT BT JU EPFT

/FYU XF IBWF UIJT CJH do CMPDL XJUI B DBTF FYQSFTTJPO BOE


FBDI DBTF BMTP IBT B do CMPDL JOTJEF JU 8IZ OPU SJHIU
'JSTU JU UFMMT UIF QMBZFS XIBU ZPV HVFTTFE 5IF DBTF FY
QSFTTJPO JT UP HJWF EJƵFSFOU SFTQPOTFT CBTFE PO XIFUIFS UIF
HVFTTFE DIBSBDUFS

Ƒ IBE BMSFBEZ CFFO HVFTTFE QSFWJPVTMZ

Ƒ JT JO UIF XPSE BOE OFFET UP CF ƶMMFE JO

Ƒ PS XBT OPU QSFWJPVTMZ HVFTTFE CVU BMTP JTOƊU JO UIF QV[[MF


XPSE

%FTQJUF UIF JOJUJBM BQQFBSBODF PG DPNQMFYJUZ NPTU PG UIJT


JT TZOUBY ZPVƊWF TFFO CFGPSF BOE ZPV DBO MPPL UISPVHI JU TUFQ
CZTUFQ BOE TFF XIBUƊT HPJOH PO
$)"15&3  #6*-%*/( 130+&$54 

handleGuess :: Puzzle -> Char -> IO Puzzle


handleGuess puzzle guess = do
putStrLn $ "Your guess was: " ++ [guess]
case (charInWord puzzle guess
, alreadyGuessed puzzle guess) of
(_, True) -> do
putStrLn "You already guessed that\
\ character, pick something else!"
return puzzle
(True, _) -> do
putStrLn "This character was in the word,\
\ filling in the word accordingly"
return (fillInCharacter puzzle guess)
(False, _) -> do
putStrLn "This character wasn't in\
\ the word, try again."
return (fillInCharacter puzzle guess)

"MM SJHIU OFYU XF OFFE UP EFWJTF B XBZ UP TUPQ UIF HBNF BǒFS
B DFSUBJO OVNCFS PG HVFTTFT )BOHNBO HBNFT OPSNBMMZ TUPQ
POMZ BǒFS B DFSUBJO OVNCFS PG JODPSSFDU HVFTTFT CVU GPS UIF
TBLF PG TJNQMJDJUZ IFSF XFƊSF KVTU TUPQQJOH BǒFS B TFU OVNCFS
PG HVFTTFT XIFUIFS UIFZƊSF DPSSFDU PS OPU "HBJO UIF TZOUBY
IFSF TIPVME CF DPNQSFIFOTJCMF UP ZPV GSPN XIBU XFƊWF EPOF
TP GBS
$)"15&3  #6*-%*/( 130+&$54 

gameOver :: Puzzle -> IO ()


gameOver (Puzzle wordToGuess _ guessed) =
if (length guessed) > 7 then
do putStrLn "You lose!"
putStrLn $ "The word was: " ++ wordToGuess
exitSuccess
else return ()

/PUJDF UIF XBZ JUƊT XSJUUFO TBZT ZPV MPTF BOE FYJUT UIF HBNF
PODF ZPVƊWF HVFTTFE TFWFO DIBSBDUFST FWFO JG UIF ƶOBM TFWFOUI

HVFTT JT UIF ƶOBM MFUUFS UP ƶMM JOUP UIF XPSE 5IFSF BSF PG DPVSTF
XBZT UP NPEJGZ UIBU UP NBLF JU NPSF UIF XBZ ZPVƊE FYQFDU B
IBOHNBO HBNF UP HP BOE XF FODPVSBHF ZPV UP QMBZ XJUI UIBU
/FYU XF OFFE UP QSPWJEF B XBZ UP FYJU BǒFS XJOOJOH UIF
HBNF 8F TIPXFE ZPV IPX UIF DPNCJOBUJPO PG isJust BOE all
XPSLT FBSMJFS JO UIF DIBQUFS BOE ZPV DBO TFF UIBU JO BDUJPO
IFSF 3FDBMM UIBU PVS QV[[MF XPSE JT B MJTU PG Maybe WBMVFT TP
XIFO FBDI DIBSBDUFS JT SFQSFTFOUFE CZ B Just Char SBUIFS UIBO
B Nothing ZPV XJO UIF HBNF BOE XF FYJU

gameWin :: Puzzle -> IO ()


gameWin (Puzzle _ filledInSoFar _) =
if all isJust filledInSoFar then
do putStrLn "You win!"
exitSuccess
else return ()
$)"15&3  #6*-%*/( 130+&$54 

/FYU JT UIF JOTUSVDUJPO GPS SVOOJOH B HBNF )FSF XF VTF


forever TP UIBU UIJT XJMM FYFDVUF UIJT TFSJFT PG BDUJPOT JOEFG
JOJUFMZ

runGame :: Puzzle -> IO ()


runGame puzzle = forever $ do
gameOver puzzle
gameWin puzzle
putStrLn $ "Current puzzle is: " ++ show puzzle
putStr "Guess a letter: "
guess <- getLine
case guess of
[c] -> handleGuess puzzle c >>= runGame
_ -> putStrLn "Your guess must\
\ be a single character"

"OE ƶOBMMZ IFSF JT main CSJOHJOH FWFSZUIJOH UPHFUIFS JU


HFUT B XPSE GSPN UIF XPSE MJTU XF HFOFSBUFE HFOFSBUFT B GSFTI
QV[[MF BOE UIFO FYFDVUFT UIF runGame BDUJPOT XF KVTU TBX BCPWF
VOUJM TVDI UJNF BT ZPV HVFTT BMM UIF DIBSBDUFST JO UIF XPSE
DPSSFDUMZ PS IBWF NBEF TFWFO HVFTTFT XIJDIFWFS DPNFT ƶSTU
$)"15&3  #6*-%*/( 130+&$54 

main :: IO ()
main = do
word <- randomWord'
let puzzle = freshPuzzle (fmap toLower word)
runGame puzzle

 "EEJOH B OFXUZQF


"OPUIFS XBZ ZPV DPVME NPEJGZ ZPVS DPEF JO UIF BCPWF BOE
HBJO QFSIBQT NPSF DMBSJUZ JO QMBDFT JT XJUI UIF VTF PG OFXUZQF

-- replace this synonym with the newtype


-- type WordList = [String]

newtype WordList =
WordList [String]
deriving (Eq, Show)

allWords :: IO WordList
allWords = do
dict <- readFile "data/dict.txt"
return $ WordList (lines dict)
$)"15&3  #6*-%*/( 130+&$54 

gameWords :: IO WordList
gameWords = do
(WordList aw) <- allWords
return $ WordList (filter gameLength aw)
where gameLength w =
let l = length (w :: String)
in l > minWordLength && l < maxWordLength

randomWord :: WordList -> IO String


randomWord (WordList wl) = do
randomIndex <- randomRIO (0, (length wl) - 1)
return $ wl !! randomIndex

 $IBQUFS FYFSDJTFT


)BOHNBO HBNF MPHJD
:PV NBZ IBWF OPUJDFE XIFO ZPV XFSF QMBZJOH XJUI UIF IBOH
NBO HBNF UIBU UIFSF BSF TPNF XFJSE UIJOHT BCPVU JUT HBNF
MPHJD

Ƒ BMUIPVHI JU DBO QMBZ XJUI XPSET VQ UP  DIBSBDUFST MPOH


ZPV POMZ HFU UP HVFTT  DIBSBDUFST

Ƒ JU FOET UIF HBNF BǒFS  HVFTTFT XIFUIFS UIFZ XFSF DPSSFDU


PS JODPSSFDU
$)"15&3  #6*-%*/( 130+&$54 

Ƒ JG ZPVS UI HVFTT TVQQMJFT UIF MBTU MFUUFS JO UIF XPSE JU NBZ
TUJMM UFMM ZPV ZPV MPTU

Ƒ JU QJDLT TPNF WFSZ TUSBOHF XPSET UIBU ZPV EJEOƊU TVTQFDU


XFSF FWFO JO UIF EJDUJPOBSZ

5IFTF NBLF JU VOMJLF IBOHNBO BT ZPV NJHIU IBWF QMBZFE JU


JO UIF QBTU 0SEJOBSJMZ POMZ JODPSSFDU HVFTTFT DPVOU BHBJOTU
ZPV TP ZPV DBO NBLF BT NBOZ DPSSFDU HVFTTFT BT ZPV OFFE
UP ƶMM JO UIF XPSE .PEJGZJOH UIF HBNF TP UIBU JU FJUIFS HJWFT
ZPV NPSF HVFTTFT CFGPSF UIF HBNF FOET PS POMZ VTFT TIPSUFS
XPSET PS CPUI
JOWPMWFT POMZ B DPVQMF PG VODPNQMJDBUFE TUFQT
" CJU NPSF DPNQMJDBUFE CVU XPSUI BUUFNQUJOH BT BO FYFSDJTF
JT DIBOHJOH UIF HBNF TP UIBU BT XJUI OPSNBM IBOHNBO POMZ
JODPSSFDU HVFTTFT DPVOU UPXBSET UIF HVFTT MJNJU

.PEJGZJOH DPEF
 $JQIFST 0QFO ZPVS $JQIFST NPEVMF BOE NPEJGZ JU TP UIBU
UIF $BFTBS BOE 7JHFO¨SF DJQIFST XPSL XJUI VTFS JOQVU

 )FSF JT B WFSZ TJNQMF TIPSU CMPDL PG DPEF /PUJDF JU IBT


B forever UIBU XJMM NBLF JU LFFQ SVOOJOH PWFS BOE PWFS
BHBJO -PBE JU JOUP ZPVS 3&1- BOE UFTU JU PVU 5IFO SFGFS
CBDL UP UIF DIBQUFS BOE NPEJGZ JU UP FYJU TVDDFTTGVMMZ BǒFS
B 'BMTF SFTVMU
$)"15&3  #6*-%*/( 130+&$54 

import Control.Monad

palindrome :: IO ()
palindrome = forever $ do
line1 <- getLine
case (line1 == reverse line1) of
True -> putStrLn "It's a palindrome!"
False -> putStrLn "Nope!"

 *G ZPV USJFE VTJOH palindrome PO B TFOUFODF TVDI BT ƌ.BEBN


*ƊN "EBN ƍ ZPV NBZ IBWF OPUJDFE UIBU QBMJOESPNF DIFDLFS
EPFTOƊU XPSL PO UIBU .PEJGZJOH UIF BCPWF TP UIBU JU XPSLT
PO TFOUFODFT UPP JOWPMWFT TFWFSBM TUFQT :PV NBZ OFFE
UP SFGFS CBDL UP QSFWJPVT FYBNQMFT JO UIF DIBQUFS UP HFU
JEFBT GPS QSPQFS PSEFSJOH BOE OFTUJOH :PV NBZ XJTI UP
JNQPSU %BUB$IBS UP VTF UIF GVODUJPO toLower )BWF GVO
$)"15&3  #6*-%*/( 130+&$54 

 type Name = String


type Age = Integer

data Person = Person Name Age deriving Show

data PersonInvalid = NameEmpty


| AgeTooLow
| PersonInvalidUnknown String
deriving (Eq, Show)

mkPerson :: Name
-> Age
-> Either PersonInvalid Person
mkPerson name age
| name /= "" && age > 0 = Right $ Person name age
| name == "" = Left NameEmpty
| not (age > 0) = Left AgeTooLow
| otherwise = Left $ PersonInvalidUnknown $
"Name was: " ++ show name ++
" Age was: " ++ show age

:PVS KPC JT UP XSJUF UIF GPMMPXJOH GVODUJPO XJUIPVU NPEJ


GZJOH UIF DPEF BCPWF
$)"15&3  #6*-%*/( 130+&$54 

gimmePerson :: IO ()
gimmePerson = undefined

4JODF IO () JT BCPVU UIF MFBTU JOGPSNBUJWF UZQF JNBHJOBCMF


XFƊMM UFMM XIBU JU TIPVME EP

B
*U TIPVME QSPNQU UIF VTFS GPS B OBNF BOE BHF JOQVU
C
*U TIPVME BUUFNQU UP DPOTUSVDU B 1FSTPO WBMVF VTJOH
UIF OBNF BOE BHF UIF VTFS FOUFSFE :PVƊMM OFFE UIF
read GVODUJPO GPS "HF CFDBVTF JUƊT BO *OUFHFS SBUIFS
UIBO B 4USJOH
D
*G JU DPOTUSVDUFE B TVDDFTTGVM QFSTPO JU TIPVME QSJOU
ƍ:BZ 4VDDFTTGVMMZ HPU B QFSTPOƍ GPMMPXFE CZ UIF 1FS
TPO WBMVF
E
*G JU HPU BO FSSPS WBMVF SFQPSU UIBU BO FSSPS PDDVSSFE
BOE QSJOU UIF FSSPS

 'PMMPXVQ SFTPVSDFT


 4UBDL
https://github.com/commercialhaskell/stack

 )PX * 4UBSU )BTLFMM


http://bitemyapp.com/posts/2014-11-18-how-i-start-haskell.
html
$)"15&3  #6*-%*/( 130+&$54 

 $BCBM '"2
https://www.haskell.org/cabal/FAQ.html

 $BCBM VTFSƊT HVJEF


https://www.haskell.org/cabal/users-guide/

 " (FOUMF *OUSPEVDUJPO UP )BTLFMM .PEVMFT DIBQUFS


https://www.haskell.org/tutorial/modules.html
$IBQUFS 

5FTUJOH

8FƊWF UFOEFE UP GPSHFU


UIBU OP DPNQVUFS XJMM
FWFS BTL B OFX RVFTUJPO

(SBDF .VSSBZ )PQQFS


$)"15&3  5&45*/( 

 5FTUJOH
5IJT DIBQUFS MJLF UIF POF CFGPSF JU JT NPSF GPDVTFE PO QSBDUJDBM
NBUUFST SBUIFS UIBO XSJUJOH )BTLFMM DPEF QFS TF 8F XJMM CF
DPWFSJOH UXP UFTUJOH MJCSBSJFT GPS )BTLFMM UIFSF BSF PUIFST
BOE
IPX BOE XIFO UP VTF UIFN :PV XJMM OPU CF XSJUJOH NVDI PG
UIF DPEF JO UIF DIBQUFS PO ZPVS PXO JOTUFBE QMFBTF GPMMPX
BMPOH CZ FOUFSJOH JU JOUP ƶMFT BT EJSFDUFE ZPV XJMM MFBSO NPSF
JG ZPV UZQF SBUIFS UIBO DPQZ BOE QBTUF
 "U UIF FOE PG UIF
DIBQUFS UIFSF BSF B OVNCFS PG FYFSDJTFT UIBU BTL ZPV UP XSJUF
ZPVS PXO UFTUT GPS QSBDUJDF
5FTUJOH JT B DPSF QBSU PG UIF XPSLJOH QSPHSBNNFSƊT UPPMLJU
BOE )BTLFMM JT OP FYDFQUJPO 8FMMTQFDJƶFE UZQFT DBO FOBCMF
QSPHSBNNFST UP BWPJE NBOZ PCWJPVT BOE UFEJPVT UFTUT UIBU
NJHIU PUIFSXJTF CF OFDFTTBSZ UP NBJOUBJO JO VOUZQFE QSPHSBN
NJOH MBOHVBHFT CVU UIFSFƊT TUJMM B MPU PG WBMVF UP CF PCUBJOFE
JO FYFDVUBCMF TQFDJƶDBUJPOT 5IJT DIBQUFS XJMM JOUSPEVDF ZPV
UP UFTUJOH NFUIPET GPS )BTLFMM
5IJT DIBQUFS XJMM DPWFS

Ƒ UIF XIBUT BOE XIZT PG UFTUJOH

Ƒ VTJOH UIF UFTUJOH MJCSBSJFT )TQFD BOE 2VJDL$IFDL

Ƒ B CJU PG GVO XJUI .PSTF DPEF


$)"15&3  5&45*/( 

 " RVJDL UPVS PG UFTUJOH GPS UIF


VOJOJUJBUFE
8IFO XF XSJUF )BTLFMM XF SFMZ PO UIF DPNQJMFS UP KVEHF GPS
VT XIFUIFS PVS DPEF JT XFMM GPSNFE 5IBU QSFWFOUT B HSFBU
OVNCFS PG FSSPST CVU JU EPFT OPU QSFWFOU UIFN BMM *U JT TUJMM
QPTTJCMF UP XSJUF XFMMUZQFE DPEF UIBU EPFTOƊU QFSGPSN BT FY
QFDUFE BOE SVOUJNF FSSPST DBO TUJMM PDDVS 5IBUƊT XIFSF UFTUJOH
DPNFT JO
*O HFOFSBM UFTUT BMMPX ZPV UP TUBUF BO FYQFDUBUJPO BOE UIFO
WFSJGZ UIBU UIF SFTVMU PG BO PQFSBUJPO NFFUT UIBU FYQFDUBUJPO
5IFZ BMMPX ZPV UP WFSJGZ UIBU ZPVS DPEF XJMM EP XIBU ZPV XBOU
XIFO FYFDVUFE
'PS UIF TBLF PG TJNQMJDJUZ XFƊMM TBZ UIFSF BSF UXP CSPBE DBUF
HPSJFT PG UFTUJOH VOJU UFTUJOH BOE QSPQFSUZ UFTUJOH 6OJU UFTUJOH
UFTUT UIF TNBMMFTU BUPNJD VOJUT PG TPǒXBSF JOEFQFOEFOUMZ PG
POF BOPUIFS 6OJU UFTUJOH BMMPXT UIF QSPHSBNNFS UP DIFDL UIBU
FBDI GVODUJPO JT QFSGPSNJOH UIF UBTL JU JT NFBOU UP EP :PV
BTTFSU UIBU XIFO UIF DPEF SVOT XJUI B TQFDJƶFE JOQVU UIF SFTVMU
JT FRVBM UP UIF SFTVMU ZPV XBOU
4QFD UFTUJOH JT B TPNFXIBU OFXFS WFSTJPO PG VOJU UFTUJOH
-JLF VOJU UFTUJOH JU UFTUT TQFDJƶD GVODUJPOT JOEFQFOEFOUMZ BOE
BTLT ZPV UP BTTFSU UIBU XIFO HJWFO UIF EFDMBSFE JOQVU UIF SFTVMU
PG UIF PQFSBUJPO XJMM CF FRVBM UP UIF EFTJSFE SFTVMU 8IFO ZPV
SVO UIF UFTU UIF DPNQVUFS DIFDLT UIBU UIF FYQFDUFE SFTVMU JT
$)"15&3  5&45*/( 

FRVBM UP UIF BDUVBM SFTVMU BOE FWFSZPOF NPWFT PO XJUI UIFJS EBZ
4PNF QFPQMF QSFGFS TQFD UFTUJOH UP VOJU UFTUJOH CFDBVTF TQFD
UFTUJOH JT NPSF PǒFO XSJUUFO JO UFSNT PG BTTFSUJPOT UIBU BSF JO
IVNBOSFBEBCMF MBOHVBHF 5IJT DBO CF FTQFDJBMMZ WBMVBCMF JG
OPOQSPHSBNNFST OFFE UP CF BCMF UP SFBE BOE JOUFSQSFU UIF
SFTVMUT PG UIF UFTUT ƈ UIFZ DBO SFBE UIF &OHMJTIMBOHVBHF SFTVMUT
PG UIF UFTUT BOE JO TPNF DBTFT XSJUF UFTUT UIFNTFMWFT
)BTLFMM QSPWJEFT MJCSBSJFT GPS CPUI VOJU BOE TQFD UFTUJOH
8FƊMM GPDVT PO TQFD UFTUJOH XJUI UIF )TQFD MJCSBSZ JO UIJT DIBQ
UFS CVU )6OJU JT BMTP BWBJMBCMF 0OF MJNJUBUJPO UP VOJU BOE TQFD
UFTUJOH JT UIBU UIFZ UFTU BUPNJD VOJUT PG DPEF JOEFQFOEFOUMZ TP
UIFZ EP OPU WFSJGZ UIBU BMM UIF QJFDFT XPSL UPHFUIFS QSPQFSMZ
1SPQFSUZ UFTUJOH JT B EJƵFSFOU CFBTU 5IJT LJOE PG UFTUJOH
XBT QJPOFFSFE JO )BTLFMM CFDBVTF UIF UZQF TZTUFN BOE TUSBJHIU
GPSXBSE MPHJD PG UIF MBOHVBHF MFOE UIFNTFMWFT UP QSPQFSUZ
UFTUT CVU JU IBT TJODF CFFO BEPQUFE CZ PUIFS MBOHVBHFT BT XFMM
1SPQFSUZ UFTUT UFTU UIF GPSNBM QSPQFSUJFT PG QSPHSBNT XJUIPVU
SFRVJSJOH GPSNBM QSPPGT CZ BMMPXJOH ZPV UP FYQSFTT B USVUI
WBMVFE VOJWFSTBMMZ RVBOUJƶFE UIBU JT XJMM BQQMZ UP BMM DBTFT

GVODUJPO ƈ VTVBMMZ FRVBMJUZ ƈ XIJDI XJMM UIFO CF DIFDLFE


BHBJOTU SBOEPNMZ HFOFSBUFE JOQVUT
5IF JOQVUT BSF HFOFSBUFE SBOEPNMZ CZ UIF TUBOEBSE GVOD
UJPOT JOTJEF UIF 2VJDL$IFDL MJCSBSZ XF VTF GPS QSPQFSUZ UFTUJOH
5IJT SFMJFT PO UIF UZQF TZTUFN UP LOPX XIBU LJOET PG EBUB UP
HFOFSBUF 5IF EFGBVMU TFUUJOH JT GPS  JOQVUT UP CF HFOFSBUFE
HJWJOH ZPV  SFTVMUT *G JU GBJMT BOZ POF PG UIFTF UIFO ZPV
$)"15&3  5&45*/( 

LOPX ZPVS QSPHSBN EPFTOƊU IBWF UIF TQFDJƶFE QSPQFSUZ *G JU


QBTTFT ZPV DBOƊU CF QPTJUJWF JU XJMM OFWFS GBJM CFDBVTF UIF EBUB
BSF SBOEPNMZ HFOFSBUFE ƈ UIFSF DPVME CF B XFJSE FEHF DBTF
PVU UIFSF UIBU XJMM DBVTF ZPVS TPǒXBSF UP GBJM 2VJDL$IFDL JT
DMFWFSMZ XSJUUFO UP CF BT UIPSPVHI BT QPTTJCMF BOE XJMM VTVBMMZ
DIFDL UIF NPTU DPNNPO FEHF DBTFT GPS FYBNQMF FNQUZ MJTUT
BOE UIF maxBound BOE minBoundT PG UIF UZQFT JO RVFTUJPO XIFSF
BQQSPQSJBUF
 :PV DBO BMTP DIBOHF UIF TFUUJOH TP UIBU JU SVOT
NPSF UFTUT
1SPQFSUZ UFTUJOH JT GBOUBTUJD GPS FOTVSJOH UIBU ZPVƊWF NFU
UIF NJOJNVN SFRVJSFNFOUT UP TBUJTGZ MBXT TVDI BT UIF MBXT
PG NPOBET PS CBTJD BTTPDJBUJWJUZ *U JT OPU BQQSPQSJBUF GPS BMM
QSPHSBNT UIPVHI BT JU JT OPU VTFGVM GPS UJNFT XIFO UIFSF BSF
OP BTTFSUBCMF USVUIWBMVFE QSPQFSUJFT PG UIF TPǒXBSF

 $POWFOUJPOBM UFTUJOH


8F BSF HPJOH UP VTF UIF MJCSBSZ )TQFD UP EFNPOTUSBUF B TJNQMF
UFTU DBTF CVU XFƊSF OPU HPJOH UP FYQMBJO )TQFD EFFQMZ 5IF
DVSSFOU DIBQUFS XJMM FRVJQ ZPV XJUI B NFBOT PG XSJUJOH UFTUT GPS
ZPVS DPEF MBUFS CVU JUƊT OPU OFDFTTBSZ UP VOEFSTUBOE UIF EFUBJMT
PG IPX UIF MJCSBSZ XPSLT UP EP UIBU 4PNF PG UIF DPODFQUT
)TQFD MFBOT PO TVDI BT GVODUPS BQQMJDBUJWF BOE NPOBE BSF
DPWFSFE MBUFS BT JOEFQFOEFOU DPODFQUT

http://hackage.haskell.org/package/hspec
$)"15&3  5&45*/( 

'JSTU MFUƊT DPNF VQ XJUI B TJNQMF UFTU DBTF GPS BEEJUJPO


(FOFSBMMZ XF XBOU UP NBLF B $BCBM QSPKFDU FWFO GPS TNBMM
FYQFSJNFOUT )BWJOH B QFSNBOFOU QSPKFDU GPS FYQFSJNFOUT
DBO FMJNJOBUF TPNF PG UIJT PWFSIFBE CVU XFƊMM BTTVNF ZPV
IBWFOƊU EPOF UIJT ZFU BOE TUBSU B TNBMM $BCBM QSPKFDU

-- Addition.cabal
name: addition
version: 0.1.0.0
license-file: LICENSE
author: Chicken Little
maintainer: [email protected]
category: Text
build-type: Simple
cabal-version: >=1.10

library
exposed-modules: Addition
ghc-options: -Wall -fwarn-tabs
build-depends: base >=4.7 && <5
, hspec
hs-source-dirs: .
default-language: Haskell2010

/PUF XFƊWF TQFDJƶFE UIF hspec EFQFOEFODZ CVU OPU B WFSTJPO


SBOHF GPS JU :PVƊMM QSPCBCMZ XBOU XIBUFWFS UIF OFXFTU WFSTJPO
$)"15&3  5&45*/( 

PG JU JT CVU DBO QSPCBCMZ HFU BXBZ XJUI OPU TQFDJGZJOH JU GPS


OPX
/FYU XFƊMM NBLF UIF Addition NPEVMF FYQPTFENPEVMFT
JO
UIF TBNF EJSFDUPSZ BT PVS $BCBM ƶMF 5IJT JT XIZ UIF hs-source-dirs
PQUJPO JO UIF MJCSBSZ TUBO[B XBT TFU UP . ƈ UIJT JT UIF DPOWFOUJPO
GPS SFGFSSJOH UP UIF DVSSFOU EJSFDUPSZ
'PS OPX XFƊMM XSJUF B TJNQMF QMBDFIPMEFS GVODUJPO KVTU UP
NBLF TVSF FWFSZUIJOHƊT XPSLJOH

-- Addition.hs
module Addition where

sayHello :: IO ()
sayHello = putStrLn "hello!"

5IFO ZPV DBO DSFBUF BO FNQUZ -*$&/4& ƶMF TP UIF CVJME


EPFTOƊU DPNQMBJO

$ touch LICENSE

:PVS MPDBM QSPKFDU EJSFDUPSZ TIPVME MPPL MJLF UIJT OPX CFGPSF
IBWJOH SVO BOZ 4UBDL DPNNBOET

$ tree
.
├── Addition.hs
└── addition.cabal
└── LICENSE
$)"15&3  5&45*/( 

5IF OFYU TUFQT BSF UP JOJUJBMJ[F UIF 4UBDL ƶMF GPS EFTDSJCJOH
XIBU TOBQTIPU PG 4UBDLBHF XFƊMM VTF

$ stack init

5IFO XFƊMM XBOU UP CVJME PVS QSPKFDU XIJDIƊMM BMTP JOTUBMM UIF
EFQFOEFODJFT XF OFFE

$ stack build

*G UIBU TVDDFFEFE MFUƊT ƶSF VQ B 3&&&&&&&1- BOE TFF JG XF


DBO DBMM sayHello

$ stack ghci

[some noise about configuring, loading packages, etc.]

Ok, modules loaded: Addition.


Prelude> sayHello
hello!

*G ZPV HPU IFSF ZPVƊWF HPU B XPSLJOH UFTU CFE GPS NBLJOH B
TJNQMF UFTU DBTF JO )TQFD

5SVUI BDDPSEJOH UP )TQFD


/FYU XFƊMM BEE UIF JNQPSU PG )TQFDƊT QSJNBSZ NPEVMF
$)"15&3  5&45*/( 

module Addition where

import Test.Hspec

sayHello :: IO ()
sayHello = putStrLn "hello!"

/PUF UIBU BMM PG ZPVS JNQPSUT NVTU PDDVS BǒFS UIF NPEVMF
IBT CFFO EFDMBSFE BOE CFGPSF BOZ FYQSFTTJPOT IBWF CFFO EF
ƶOFE JO ZPVS NPEVMF :PV NBZ IBWF FODPVOUFSFE BO FSSPS PS
B NJTUBLF NJHIUƊWF CFFO NBEF )FSF BSF B DPVQMF PG FYBNQMFT

module Addition where

sayHello :: IO ()
sayHello = putStrLn "hello!"

import Test.Hspec

)FSF XF QVU BO JNQPSU BǒFS BU MFBTU POF EFDMBSBUJPO 5IF


DPNQJMFS QBSTFS EPFTOƊU IBWF B NFBOT PG SFDPHOJ[JOH UIJT TQF
DJƶD NJTUBLF TP JU DBOƊU UFMM ZPV QSPQFSMZ XIBU UIF FSSPS JT

Prelude> :r
[1 of 1] Compiling Addition

Addition.hs:7:1: parse error on input ‘import’


$)"15&3  5&45*/( 

Failed, modules loaded: none.

8IBU FMTF NBZ IBWF HPOF XSPOH 8FMM XF NJHIU IBWF UIF
QBDLBHF hspec JOTUBMMFE CVU OPU JODMVEFE JO PVS build-depends
GPS PVS QSPKFDU /PUF ZPVƊMM OFFE UP RVJU BOE SFPQFO UIF 3&1-
JG ZPVƊWF NBEF BOZ DIBOHFT UP ZPVS .cabal ƶMF UP SFQSPEVDF
UIJT FSSPS PS ƶYFE B NJTUBLF

$ stack build
{... noise ...}

Could not find module ‘Test.Hspec’


It is a member of the hidden package
‘hspec-2.2.3@hspec_JWyjr3DNMsw1kiPzf88M5w’.
Perhaps you need to add ‘hspec’ to the
build-depends in your .cabal file.

Use -v to see a list of the files searched for.


{... other noise ...}

Process exited with code: ExitFailure 1

*G ZPV DIBOHFE BOZUIJOH JO PSEFS UP UFTU UIFTF FSSPS NPEFT


ZPVƊMM OFFE UP BEE )TQFD CBDL UP ZPVS build-depends BOE SFJO
TUBMM JU *G )TQFD JT MJTUFE JO ZPVS EFQFOEFODJFT stack build XJMM
TFU ZPV SJHIU
$)"15&3  5&45*/( 

"TTVNJOH FWFSZUIJOH JT JO PSEFS BOE Test.Hspec JT CFJOH


JNQPSUFE XF DBO EP B MJUUMF FYQMPSBUJPO 8F DBO VTF UIF :browse
DPNNBOE UP HFU B MJTUJOH PG UZQFT GSPN B NPEVMF BOE HFU B
UIPVTBOEGPPUWJFX PG XIBU JU PƵFST

Prelude> :browse Test.Hspec


context :: String -> SpecWith a -> SpecWith a
example :: Expectation -> Expectation
specify :: Example a => String -> a -> SpecWith (Arg a)
(... list goes on for awhile ..)
Prelude>

:browse JT NPSF VTFGVM XIFO ZPV BMSFBEZ IBWF TPNF GBNJM


JBSJUZ XJUI UIF MJCSBSZ BOE IPX JU XPSLT 8IFO ZPVƊSF VTJOH
BO VOGBNJMJBS MJCSBSZ EPDVNFOUBUJPO JT FBTJFS UP EJHFTU (PPE
EPDVNFOUBUJPO FYQMBJOT IPX JNQPSUBOU QJFDFT PG UIF MJCSBSZ
XPSL BOE HJWFT FYBNQMFT PG UIFJS VTF 5IJT JT FTQFDJBMMZ WBMV
BCMF XIFO FODPVOUFSJOH OFX DPODFQUT "T JU IBQQFOT )TQFD
IBT TPNF QSFUUZ HPPE EPDVNFOUBUJPO BU UIFJS XFCTJUF

0VS ƶSTU )TQFD UFTU


-FUƊT BEE B UFTU BTTFSUJPO UP PVS NPEVMF OPX *G ZPV HMBODF
BU UIF EPDVNFOUBUJPO ZPVƊMM TFF UIBU PVS FYBNQMF JTOƊU WFSZ
JOUFSFTUJOH CVU XFƊMM NBLF JU TPNFXIBU NPSF JOUFSFTUJOH TPPO

http://hspec.github.io/
$)"15&3  5&45*/( 

module Addition where

import Test.Hspec

main :: IO ()
main = hspec $ do
describe "Addition" $ do
it "1 + 1 is greater than 1" $ do
(1 + 1) > 1 `shouldBe` True

8FƊWF BTTFSUFE JO CPUI &OHMJTI BOE DPEF UIBU (1 + 1) TIPVME


CF HSFBUFS UIBO  BOE UIBU JT XIBU )TQFD XJMM UFTU GPS VT :PV
NBZ SFDPHOJ[F UIF do OPUBUJPO GSPN UIF QSFWJPVT DIBQUFS "T
XF TBJE UIFO UIJT TZOUBY BMMPXT VT UP TFRVFODF NPOBEJD BDUJPOT
*O UIF QSFWJPVT DIBQUFS UIF NPOBE JO RVFTUJPO XBT IO
)FSF XFƊSF OFTUJOH NVMUJQMF do CMPDLT 5IF UZQF PG UIF do
CMPDLT QBTTFE UP hspec describe BOE it BSFOƊU IO () CVU TPNF
UIJOH NPSF TQFDJƶD UP )TQFD 5IFZ SFTVMU JO IO () JO UIF FOE
CVU UIFSF BSF PUIFS NPOBET JOWPMWFE 8F IBWFOƊU DPWFSFE NPO
BET ZFU BOE UIJT XPSLT ƶOF XJUIPVU VOEFSTUBOEJOH QSFDJTFMZ
IPX JU XPSLT TP MFUƊT KVTU SPMM XJUI JU GPS OPX
/PUF UIBU ZPVƊMM HFU XBSOJOHT BCPVU UIF Num a => a MJUFSBMT
HFUUJOH EFGBVMUFE UP Integer :PV DBO JHOPSF UIJT PS BEE FYQMJDJU
UZQF TJHOBUVSFT JU JT VQ UP ZPV 8JUI UIF BCPWF DPEF JO QMBDF
XF DBO MPBE PS SFMPBE PVS NPEVMF BOE SVO main UP TFF UIF UFTU
SFTVMUT
$)"15&3  5&45*/( 

Prelude> main

Addition
1 + 1 is greater than 1

Finished in 0.0041 seconds


1 example, 0 failures

0, TP XIBU IBQQFOFE IFSF #BTJDBMMZ )TQFD SVOT ZPVS


DPEF BOE WFSJƶFT UIBU UIF BSHVNFOUT ZPV QBTTFE UP shouldBe
BSF FRVBM -FUƊT MPPL BU UIF UZQFT

shouldBe :: (Eq a, Show a) => a -> a -> Expectation

-- contrast with

(==) :: Eq a => a -> a -> Bool

*O B TFOTF JUƊT BO BVHNFOUFE == FNCFEEFE JO )TQFDƊT NPEFM


PG UIF VOJWFSTF *U OFFET UIF Show JOTUBODF JO PSEFS UP SFOEFS B
WBMVF 5IBU JT UIF Show JOTUBODF BMMPXT )TQFD UP TIPX ZPV UIF
SFTVMU PG UIF UFTUT OPU KVTU SFUVSO B Bool WBMVF
-FUƊT BEE BOPUIFS UFTU POF UIBU SFBET B MJUUMF EJƵFSFOUMZ
$)"15&3  5&45*/( 

main :: IO ()
main = hspec $ do
describe "Addition" $ do
it "1 + 1 is greater than 1" $ do
(1 + 1) > 1 `shouldBe` True
it "2 + 2 is equal to 4" $ do
2 + 2 `shouldBe` 4

.PEJGZ ZPVS EFTDSJCF CMPDL BCPVU Addition TP UIBU JU MPPLT


MJLF UIF BCPWF BOE SVO JU JO UIF 3&1-

Prelude> main

Addition
1 + 1 is greater than 1
2 + 2 is equal to 4

Finished in 0.0004 seconds


2 examples, 0 failures

'PS GVO XFƊMM MPPL CBDL UP TPNFUIJOH ZPV XSPUF FBSMZ JO UIF
CPPL BOE XSJUF B TIPSU )TQFD UFTU GPS JU #BDL JO UIF 3FDVSTJPO
DIBQUFS XF XSPUF PVS PXO EJWJTJPO GVODUJPO UIBU MPPLFE MJLF
UIJT
$)"15&3  5&45*/( 

dividedBy :: Integral a => a -> a -> (a, a)


dividedBy num denom = go num denom 0
where go n d count
| n < d = (count, n)
| otherwise = go (n - d) d (count + 1)

8F XBOU UP UFTU UIBU UP TFF UIBU JU XPSLT BT JU TIPVME 5P LFFQ


UIJOHT TJNQMF XF BEEFE dividedBy UP PVS Addition.hs ƶMF BOE
UIFO SFXSPUF UIF )TQFD UFTUT UIBU XFSF BMSFBEZ UIFSF 8F XBOU
UP UFTU UIBU UIF GVODUJPO JT CPUI TVCUSBDUJOH UIF DPSSFDU OVNCFS
PG UJNFT BOE LFFQJOH BO BDDVSBUF DPVOU PG UIBU TVCUSBDUJPO
BOE BMTP UIBU JUƊT UFMMJOH VT UIF DPSSFDU SFNBJOEFS TP XFƊMM HJWF
)TQFD UXP UIJOHT UP UFTU GPS

main :: IO ()
main = hspec $ do
describe "Addition" $ do
it "15 divided by 3 is 5" $ do
dividedBy 15 3 `shouldBe` (5, 0)
it "22 divided by 5 is 4 remainder 2" $ do
dividedBy 22 5 `shouldBe` (4, 2)

5IBUƊT JU 8IFO XF SFMPBE Addition.hs JO PVS 3&1- XF DBO


UFTU PVS EJWJTJPO GVODUJPO

*Addition> main
$)"15&3  5&45*/( 

Addition
15 divided by 3 is 5
22 divided by 5 is 4 remainder 2

Finished in 0.0012 seconds


2 examples, 0 failures

)VSSBI 8F DBO EP BSJUINFUJD

*OUFSNJTTJPO 4IPSU &YFSDJTF


*O UIF $IBQUFS &YFSDJTFT BU UIF FOE PG 3FDVSTJPO ZPV XFSF
HJWFO UIJT FYFSDJTF
8SJUF B GVODUJPO UIBU NVMUJQMJFT UXP OVNCFST VTJOH SFDVS
TJWF TVNNBUJPO 5IF UZQF TIPVME CF (Eq a, Num a) => a -> a
-> a BMUIPVHI EFQFOEJOH PO IPX ZPV EP JU ZPV NJHIU BMTP
DPOTJEFS BEEJOH BO Ord DPOTUSBJOU
*G ZPV TUJMM IBWF ZPVS BOTXFS HSFBU *G OPU SFXSJUF JU BOE
UIFO XSJUF )TQFD UFTUT GPS JU
5IF BCPWF FYBNQMFT EFNPOTUSBUF UIF CBTJDT PG XSJUJOH JO
EJWJEVBM UFTUT UP UFTU QBSUJDVMBS WBMVFT *G ZPVƊE MJLF UP TFF B
NPSF EFWFMPQFE FYBNQMF ZPV DPVME SFGFS UP $ISJTƊT MJCSBSZ
#MPPEIPVOE

https://github.com/bitemyapp/bloodhound
$)"15&3  5&45*/( 

 &OUFS 2VJDL$IFDL


)TQFD EPFT B OJDF KPC XJUI TQFD UFTUJOH CVU XFƊSF )BTLFMM
VTFST ƈ XFƊSF OFWFS TBUJTƶFE )TQFD DBO POMZ QSPWF TPNF
UIJOH BCPVU QBSUJDVMBS WBMVFT $BO XF HFU BTTVSBODFT UIBU BSF
TUSPOHFS TPNFUIJOH DMPTFS UP QSPPGT "T JU IBQQFOT XF DBO
2VJDL$IFDL XBT UIF ƶSTU MJCSBSZ UP PƵFS XIBU JT UPEBZ DBMMFE
ƌQSPQFSUZ UFTUJOHƍ )TQFD UFTUJOH JT NPSF MJLF XIBU JT LOPXO
BT VOJU UFTUJOH ƈ UIF UFTUJOH PG JOEJWJEVBM VOJUT PG DPEF ƈ
XIFSFBT QSPQFSUZ UFTUJOH JT EPOF XJUI UIF BTTFSUJPO PG MBXT PS
QSPQFSUJFT
'JSTU XFƊMM OFFE UP BEE 2VJDL$IFDL UP PVS build-depends
0QFO ZPVS .cabal ƶMF BOE BEE JU #F TVSF UP DBQJUBMJ[F QuickCheck
VOMJLF ITQFD XIJDI CFHJOT XJUI B MPXFSDBTF ԗ
 *U TIPVME
BMSFBEZ CF JOTUBMMFE BT )TQFD IBT 2VJDL$IFDL BT B EFQFOEFODZ
CVU ZPV NBZ OFFE UP SFJOTUBMM JU stack build
 5IFO PQFO B OFX
stack ghci TFTTJPO
)TQFD IBT 2VJDL$IFDL JOUFHSBUJPO PVU PG UIF CPY TP PODF
UIBU JT EPOF BEE UIF GPMMPXJOH UP ZPVS NPEVMF

-- with your imports


import Test.QuickCheck

-- to the same describe block as the others


it "x + 1 is always greater than x" $ do
property $ \x -> x + 1 > (x :: Int)
$)"15&3  5&45*/( 

*G XF IBE OPU BTTFSUFE UIF UZQF PG ԧ JO UIF QSPQFSUZ UFTU UIF


DPNQJMFS XPVME OPU IBWF LOPXO XIBU DPODSFUF UZQF UP VTF
BOE XFƊE TFF B NFTTBHF MJLF UIJT

No instance for (Show a0) arising from a use of ‘property’


The type variable ‘a0’ is ambiguous
...
No instance for (Num a0) arising from a use of ‘+’
The type variable ‘a0’ is ambiguous
...
No instance for (Ord a0) arising from a use of ‘>’
The type variable ‘a0’ is ambiguous

"WPJE UIJT CZ BTTFSUJOH B DPODSFUF UZQF GPS FYBNQMF (x ::


Int) JO UIF QSPQFSUZ
"TTVNJOH BMM JT XFMM XIFO XF SVO JU XFƊMM TFF TPNFUIJOH
MJLF UIF GPMMPXJOH

Prelude> main

Addition
1 + 1 is greater than 1
2 + 2 is equal to 4
x + 1 is always greater than x

Finished in 0.0067 seconds


3 examples, 0 failures
$)"15&3  5&45*/( 

8IBUƊT CFJOH IJEEFO B CJU CZ )TQFD JT UIBU 2VJDL$IFDL UFTUT


NBOZ WBMVFT UP TFF JG ZPVS BTTFSUJPOT IPME GPS BMM PG UIFN *U
EPFT UIJT CZ SBOEPNMZ HFOFSBUJOH WBMVFT PG UIF UZQF ZPV TBJE
ZPV FYQFDUFE 4P JUƊMM LFFQ GFFEJOH PVS GVODUJPO SBOEPN Int
WBMVFT UP TFF JG UIF QSPQFSUZ JT FWFS GBMTF 5IF OVNCFS PG UFTUT
2VJDL$IFDL SVOT EFGBVMUT UP 

"SCJUSBSZ JOTUBODFT
2VJDL$IFDL SFMJFT PO B UZQFDMBTT DBMMFE Arbitrary BOE B OFX
UZQF DBMMFE Gen GPS HFOFSBUJOH JUT SBOEPN EBUB
arbitrary JT B WBMVF PG UZQF Gen

Prelude> :t arbitrary
arbitrary :: Arbitrary a => Gen a

5IJT JT NFSFMZ B XBZ UP TFU B EFGBVMU HFOFSBUPS GPS B UZQF


8IFO ZPV VTF UIF arbitrary WBMVF ZPV IBWF UP TQFDJGZ UIF
UZQF UP EJTQBUDI UIF SJHIU UZQFDMBTT JOTUBODF BT UZQFT BOE UZQF
DMBTTFT JOTUBODFT GPSN VOJRVF QBJSJOHT #VU UIJT JT KVTU B WBMVF
)PX EP XF TFF B MJTU PG WBMVFT PG UIF DPSSFDU UZQF
8F DBO VTF sample BOE sample' GSPN UIF Test.QuickCheck NPE
VMF JO PSEFS UP TFF TPNF SBOEPN EBUB

-- this one just prints each value on a new line


Prelude> :t sample
sample :: Show a => Gen a -> IO ()
$)"15&3  5&45*/( 

-- this one returns a list


Prelude> :t sample'
sample' :: Gen a -> IO [a]

5IF IO JT OFDFTTBSZ CFDBVTF JUƊT VTJOH B HMPCBM SFTPVSDF PG


SBOEPN WBMVFT UP HFOFSBUF UIF EBUB " DPNNPO XBZ UP HFOFS
BUF QTFVEPSBOEPN EBUB JT UP IBWF B GVODUJPO UIBU HJWFO TPNF
JOQVU ƌTFFEƍ WBMVF SFUVSOT B WBMVF BOE BOPUIFS TFFE WBMVF GPS
HFOFSBUJOH B EJƵFSFOU WBMVF :PV DBO CJOE UIF UXP BDUJPOT
UPHFUIFS BT XF FYQMBJOFE JO UIF MBTU DIBQUFS UP QBTT B OFX TFFE
WBMVF FBDI UJNF BOE LFFQ HFOFSBUJOH TFFNJOHMZ SBOEPN EBUB
*O UIJT DBTF IPXFWFS XFƊSF OPU EPJOH UIBU )FSF XFƊSF VTJOH
IO TP UIBU PVS GVODUJPO UIBU HFOFSBUFT PVS EBUB DBO SFUVSO B
EJƵFSFOU SFTVMU FBDI UJNF OPU TPNFUIJOH QVSF GVODUJPOT BSF
BMMPXFE UP EP
CZ QVMMJOH GSPN B HMPCBM SFTPVSDF PG SBOEPN
WBMVFT *G UIJT EPFTOƊU NBLF B HSFBU EFBM PG TFOTF BU UIJT QPJOU
JU XJMM CF NPSF DMFBS PODF XFƊWF DPWFSFE NPOBET BOE FWFO
NPSF TP PODF XF DPWFS IO
8F VTF UIF Arbitrary UZQFDMBTT JO PSEFS UP QSPWJEF B HFOFSB
UPS GPS sample *U JTOƊU B UFSSJCMZ QSJODJQMFE UZQFDMBTT CVU JU JT
QPQVMBS BOE VTFGVM GPS UIJT 8F TBZ JU JT VOQSJODJQMFE CFDBVTF
JU IBT OP MBXT BOE OPUIJOH TQFDJƶD JUƊT TVQQPTFE UP EP *UƊT KVTU
B DPOWFOJFOU XBZ PG QMVDLJOH B DBOPOJDBM HFOFSBUPS GPS Gen a
PVU PG UIJO BJS XJUIPVU IBWJOH UP LOPX XIFSF JU DPNFT GSPN
*G JU GFFMT B CJU MJLF ."(*$, BU UIJT QPJOU UIBUƊT ƶOF *U JT B
$)"15&3  5&45*/( 

CJU BOE UIF JOOFS XPSLJOHT PG Arbitrary BSF OPU XPSUI GVTTJOH
PWFS SJHIU OPX
"T ZPVƊMM TFF MBUFS UIJT JTOƊU OFDFTTBSZ JG ZPV IBWF B Gen WBMVF
SFBEZ UP HP BMSFBEZ Gen JT B OFXUZQF XJUI B TJOHMF UZQF BSHV
NFOU *U FYJTUT GPS XSBQQJOH VQ B GVODUJPO UP HFOFSBUF QTFVEP
SBOEPN WBMVFT 5IF GVODUJPO UBLFT BO BSHVNFOU UIBU JT VTVBMMZ
QSPWJEFE CZ TPNF LJOE PG SBOEPN WBMVF HFOFSBUPS UP HJWF ZPV
B QTFVEPSBOEPN WBMVF PG UIBU UZQF BTTVNJOH JUƊT B UZQF UIBU
IBT BO JOTUBODF PG UIF Arbitrary UZQFDMBTT
"OE UIJT JT XIBU XF HFU XIFO XF VTF UIF sample GVODUJPOT
8F VTF UIF arbitrary WBMVF CVU TQFDJGZ UIF UZQF TP UIBU JU HJWFT
VT B MJTU PG SBOEPN WBMVFT PG UIBU UZQF

Prelude> sample (arbitrary :: Gen Int)


0
-2
-1
4
-3
4
2
4
-3
2
-4
Prelude> sample (arbitrary :: Gen Double)
$)"15&3  5&45*/( 

0.0
0.13712502861905426
2.9801894108743605
-8.960645064542609
4.494161946149201
7.903662448338119
-5.221729489254451
31.64874305324701
77.43118278366954
-539.7148886375935
26.87468214215407

*G ZPV SVO sample arbitrary EJSFDUMZ JO ()$J XJUIPVU TQFDJ


GZJOH B UZQF JU XJMM EFGBVMU UIF UZQF UP () BOE HJWF ZPV B WFSZ
OJDF MJTU PG FNQUZ UVQMFT *G ZPV USZ MPBEJOH BO VOTQFDJƶFE
sample arbitrary GSPN B TPVSDF ƶMF UIPVHI ZPV XJMM HFU BO BG
GFDUJPOBUF NFTTBHF GSPN ()$ BCPVU IBWJOH BO BNCJHVPVT
UZQF 5SZ JU JG ZPV MJLF ()$J IBT TPNFXIBU EJƵFSFOU SVMFT GPS
EFGBVMU UZQFT UIBO ()$ EPFT
8F DBO TQFDJGZ PVS PXO EBUB GPS HFOFSBUJOH Gen WBMVFT *O
UIJT FYBNQMF XFƊMM TQFDJGZ B USJWJBM GVODUJPO UIBU BMXBZT SFUVSOT
B  PG UZQF Int
$)"15&3  5&45*/( 

-- the trivial generator of values

trivialInt :: Gen Int


trivialInt = return 1

:PV NBZ SFNFNCFS return GSPN UIF QSFWJPVT DIBQUFS BT


XFMM )FSF JU QSPWJEFT BO FYQFEJFOU XBZ UP DPOTUSVDU B GVODUJPO
*O UIF MBTU DIBQUFS XF OPUFE UIBU JU EPFTOƊU EP B XIPMF MPU FYDFQU
SFUVSO B WBMVF JOTJEF PG B NPOBE #FGPSF XF XFSF VTJOH JU UP
QVU B WBMVF JOUP IO CVU JUƊT OPU MJNJUFE UP VTF XJUI UIBU NPOBE

return :: Monad m => a -> m a

-- when `m` is Gen:

return :: a -> Gen a

1VUUJOH  JOUP UIF Gen NPOBE DPOTUSVDUT B HFOFSBUPS UIBU


BMXBZT SFUVSOT UIF TBNF WBMVF 
4P XIBU IBQQFOT XIFO XF TBNQMF EBUB GSPN UIJT

Prelude> sample' trivialInt


[1,1,1,1,1,1,1,1,1,1,1]

/PUJDF OPX PVS WBMVF JTOƊU arbitrary GPS TPNF UZQF CVU UIF
trivialInt WBMVF XF EFƶOFE BCPWF 5IBU HFOFSBUPS BMXBZT SF
UVSOT  TP BMM sample' DBO SFUVSO GPS VT JT B MJTU PG 
-FUƊT FYQMPSF EJƵFSFOU NFBOT PG HFOFSBUJOH WBMVFT
$)"15&3  5&45*/( 

oneThroughThree :: Gen Int


oneThroughThree = elements [1, 2, 3]

5SZ MPBEJOH UIBU WJB ZPVS Addition NPEVMF BOE BTLJOH GPS B
sample TFU PG SBOEPN oneThroughThree WBMVFT

*Addition> sample' oneThroughThree


[2,3,3,2,2,1,2,1,1,3,3]

:FQ JU HBWF VT SBOEPN WBMVFT GSPN POMZ UIBU MJNJUFE TFU


"U UIJT UJNF FBDI OVNCFS JO UIBU TFU IBT UIF TBNF DIBODF PG
TIPXJOH VQ JO PVS SBOEPN EBUB TFU 8F DPVME UJOLFS XJUI
UIPTF PEET CZ IBWJOH B MJTU XJUI SFQFBUFE FMFNFOUT UP HJWF
UIPTF FMFNFOUT B IJHIFS QSPCBCJMJUZ PG TIPXJOH VQ JO FBDI
HFOFSBUJPO

oneThroughThree :: Gen Int


oneThroughThree = elements [1, 2, 2, 2, 2, 3]

5SZ SVOOJOH sample' BHBJO XJUI UIJT TFU BOE TFF JG ZPV OP
UJDF UIF EJƵFSFODF :PV NBZ OPU PG DPVSTF CFDBVTF EVF UP
UIF OBUVSF PG QSPCBCJMJUZ UIFSF JT BU MFBTU TPNF DIBODF UIBU
 XPVMEOƊU TIPX VQ BOZ NPSF UIBO JU EJE XJUI UIF QSFWJPVT
TBNQMF
/FYU XFƊMM VTF choose BOE elements GSPN UIF 2VJDL$IFDL
MJCSBSZ BT HFOFSBUPST PG WBMVFT
$)"15&3  5&45*/( 

-- choose :: System.Random.Random a => (a, a) -> Gen a


-- elements :: [a] -> Gen a

genBool :: Gen Bool


genBool = choose (False, True)

genBool' :: Gen Bool


genBool' = elements [False, True]

genOrdering :: Gen Ordering


genOrdering = elements [LT, EQ, GT]

genChar :: Gen Char


genChar = elements ['a'..'z']

:PV TIPVME FOUFS BMM UIFTF JOUP ZPVS Addition NPEVMF MPBE
UIFN JOUP ZPVS 3&1- BOE KVTU QMBZ XJUI HFUUJOH MJTUT PG TBNQMF
EBUB GPS FBDI
0VS OFYU FYBNQMFT BSF B CJU NPSF DPNQMFY
$)"15&3  5&45*/( 

genTuple :: (Arbitrary a, Arbitrary b) => Gen (a, b)


genTuple = do
a <- arbitrary
b <- arbitrary
return (a, b)

genThreeple :: (Arbitrary a, Arbitrary b, Arbitrary c) =>


Gen (a, b, c)
genThreeple = do
a <- arbitrary
b <- arbitrary
c <- arbitrary
return (a, b, c)

)FSFƊT IPX UP VTF HFOFSBUPST XIFO UIFZ IBWF QPMZNPS


QIJD UZQF BSHVNFOUT 3FNFNCFS UIBU JG ZPV MFBWF UIF UZQFT
VOTQFDJƶFE UIF FYUFOEFE EFGBVMUJOH CFIBWJPS PG ()$J XJMM
IFMQGVMMZ
QJDL VOJU GPS ZPV 0VUTJEF PG ()$J ZPVƊMM HFU BO
FSSPS BCPVU BO BNCJHVPVT UZQF ƈ XF DPWFSFE TPNF PG UIJT
XIFO XF FYQMBJOFE UZQFDMBTTFT FBSMJFS

Prelude> sample genTuple


((),())
((),())
((),())
$)"15&3  5&45*/( 

)FSF JUƊT EFGBVMUJOH UIF Ԑ BOE ԑ UP () 8F DBO HFU NPSF


JOUFSFTUJOH PVUQVU JG XF UFMM JU XIBU XF FYQFDU Ԑ BOE ԑ UP CF
/PUF JUƊMM BMXBZT QJDL  BOE  GPS UIF ƶSTU OVNFSJD WBMVFT

Prelude> sample (genTuple :: Gen (Int, Float))


(0,0.0)
(-1,0.2516606)
(3,0.7800742)
(5,-61.62875)

8F DBO BTL GPS MJTUT BOE DIBSBDUFST PS BOZUIJOH XJUI BO


JOTUBODF PG UIF Arbitrary UZQFDMBTT

Prelude> sample (genTuple :: Gen ([()], Char))


([],'\STX')
([()],'X')
([],'?')
([],'\137')
([(),()],'\DC1')
([(),()],'z')

:PV DBO VTF :info Arbitrary JO ZPVS ()$J UP TFF XIBU JO
TUBODFT BSF BWBJMBCMF
8F DBO BMTP HFOFSBUF BSCJUSBSZ Maybe BOE Either WBMVFT
$)"15&3  5&45*/( 

genEither :: (Arbitrary a, Arbitrary b) => Gen (Either a b)


genEither = do
a <- arbitrary
b <- arbitrary
elements [Left a, Right b]

-- equal probability
genMaybe :: Arbitrary a => Gen (Maybe a)
genMaybe = do
a <- arbitrary
elements [Nothing, Just a]

-- What QuickCheck actually does


-- so you get more Just values
genMaybe' :: Arbitrary a => Gen (Maybe a)
genMaybe' = do
a <- arbitrary
frequency [ (1, return Nothing)
, (3, return (Just a))]

-- frequency :: [(Int, Gen a)] -> Gen a

'PS OPX ZPV TIPVME KVTU QMBZ XJUI UIJT JO UIF 3&1- JU XJMM
CFDPNF VTFGVM UP LOPX MBUFS PO
$)"15&3  5&45*/( 

6TJOH 2VJDL$IFDL XJUIPVU )TQFD


8F DBO BMTP VTF 2VJDL$IFDL XJUIPVU )TQFD *O UIBU DBTF XF
OP MPOHFS OFFE UP TQFDJGZ ԧ JO PVS FYQSFTTJPO CFDBVTF UIF
UZQF PG prop_additionGreater QSPWJEFT GPS JU 5IVT XF SFXSJUF
PVS QSFWJPVT FYBNQMF BT GPMMPXT

prop_additionGreater :: Int -> Bool


prop_additionGreater x = x + 1 > x

runQc :: IO ()
runQc = quickCheck prop_additionGreater

'PS OPX XF EPOƊU OFFE UP XPSSZ BCPVU IPX runQc EPFT JUT
XPSL *UƊT B HFOFSJD GVODUJPO MJLF main UIBU TJHOBMT UIBU JUƊT UJNF
UP EP TUVƵ 4QFDJƶDBMMZ JO UIJT DBTF JUƊT UJNF UP QFSGPSN UIF
2VJDL$IFDL UFTUT
/PX XIFO XF SVO JU JO UIF 3&1- JOTUFBE PG UIF main GVOD
UJPO XF XFSF DBMMJOH XJUI )TQFD XFƊMM DBMM runQc XIJDI XJMM DBMM
PO 2VJDL$IFDL UP UFTU UIF QSPQFSUZ XF EFƶOFE 8IFO XF SVO
2VJDL$IFDL EJSFDUMZ JU SFQPSUT IPX NBOZ UFTUT JU SBO

Prelude> runQc
+++ OK, passed 100 tests.

8IBU IBQQFOT JG XF BTTFSU TPNFUIJOH VOUSVF

prop_additionGreater x = x + 0 > x
$)"15&3  5&45*/( 

Prelude> :r
[1 of 1] Compiling Addition
Ok, modules loaded: Addition.
Prelude> runQc
*** Failed! Falsifiable (after 1 test):
0

$POWFOJFOUMZ 2VJDL$IFDL EPFTOƊU KVTU UFMM VT UIBU PVS UFTU


GBJMFE CVU JU UFMMT VT UIF ƶSTU JOQVU JU FODPVOUFSFE UIBU JU GBJMFE
PO *G ZPV USZ UP LFFQ SVOOJOH JU ZPV NBZ OPUJDF UIBU UIF
WBMVF UIBU JU GBJMT PO JT BMXBZT  " XIJMF BHP XF TBJE UIBU
2VJDL$IFDL IBT TPNF CVJMUJO DMFWFSOFTT BOE USJFT UP FOTVSF
UIBU DPNNPO FSSPS CPVOEBSJFT XJMM BMXBZT HFU UFTUFE 5IF
JOQVU  JT B GSFRVFOU QPJOU PG GBJMVSF TP 2VJDL$IFDL USJFT UP
FOTVSF UIBU JU JT BMXBZT UFTUFE XIFO BQQSPQSJBUF HJWFO UIF
UZQFT FUD FUD


 .PSTF DPEF


*O UIF JOUFSFTU PG QMBZJOH XJUI UFTUJOH XFƊMM XPSL UISPVHI BO
FYBNQMF QSPKFDU XIFSF XF USBOTMBUF UFYU UP BOE GSPN .PSTF
DPEF 8FƊSF HPJOH UP TUBSU B OFX QSPKFDU GPS UIJT 8IFO ZPV
EP VTF stack new project-name UP TUBSU B OFX QSPKFDU JOTUFBE PG
stack init GPS BO FYJTUJOH QSPKFDU JU BVUPNBUJDBMMZ HFOFSBUFT B
ƶMF DBMMFE Setup.hs UIBU MPPLT MJLF UIJT
$)"15&3  5&45*/( 

import Distribution.Simple
main = defaultMain

5IJT JTOƊU UFSSJCMZ JNQPSUBOU :PV SBSFMZ OFFE UP NPEJGZ


PS EP BOZUIJOH BU BMM XJUI UIF Setup.hs ƶMF BOE VTVBMMZ ZPV
TIPVMEOƊU UPVDI JU BU BMM 0DDBTJPOBMMZ ZPV NBZ OFFE UP FEJU JU
GPS DFSUBJO UBTLT TP JU JT HPPE UP SFDPHOJ[F UIBU JUƊT UIFSF
/FYU BT BMXBZT MFUƊT HFU PVS .cabal ƶMF DPOƶHVSFE QSPQFSMZ
4PNF PG UIJT XJMM CF BVUPNBUJDBMMZ HFOFSBUFE CZ ZPVS stack new
project-name CVU ZPVƊMM IBWF UP BEE UP XIBU JU HFOFSBUFT CFJOH
DBSFGVM BCPVU UIJOHT MJLF DBQJUBMJ[BUJPO BOE JOEFOUBUJPO

name: morse
version: 0.1.0.0
license-file: LICENSE
author: Chris Allen
maintainer: [email protected]
category: Text
build-type: Simple
cabal-version: >=1.10

library
exposed-modules: Morse
ghc-options: -Wall -fwarn-tabs
build-depends: base >=4.7 && <5
, containers
$)"15&3  5&45*/( 

, QuickCheck
hs-source-dirs: src
default-language: Haskell2010

executable morse
main-is: Main.hs
ghc-options: -Wall -fwarn-tabs
hs-source-dirs: src
build-depends: base >=4.7 && <5
, containers
, morse
, QuickCheck
default-language: Haskell2010

test-suite tests
ghc-options: -Wall -fno-warn-orphans
type: exitcode-stdio-1.0
main-is: tests.hs
hs-source-dirs: tests
build-depends: base
, containers
, morse
, QuickCheck
default-language: Haskell2010

/PX UIBUƊT TFU VQ BOE SFBEZ GPS VT TP UIF OFYU TUFQ JT UP NBLF
$)"15&3  5&45*/( 

PVS src EJSFDUPSZ BOE UIF ƶMF DBMMFE Morse.hs BT PVS ƌFYQPTFE
NPEVMFƍ

-- src/Morse.hs

module Morse
( Morse
, charToMorse
, morseToChar
, stringToMorse
, letterToMorse
, morseToLetter
) where

import qualified Data.Map as M

type Morse = String

8IPB UIFSF ƈ XIBUƊT BMM UIBU TUVƵ BǒFS UIF NPEVMF OBNF
5IBU JT B MJTU PG FWFSZUIJOH UIJT NPEVMF XJMM FYQPSU 8F UBMLFE
B CJU BCPVU UIJT JO UIF QSFWJPVT DIBQUFS CVU EJEOƊU NBLF VTF PG
JU *O UIF IBOHNBO HBNF XF IBE BMM PVS GVODUJPOT JO POF ƶMF
TP OPUIJOH OFFEFE UP CF FYQPSUFE

/PUB CFOF :PV EPOƊU IBWF UP TQFDJGZ FYQPSUT JO UIJT NBOOFS


#Z EFGBVMU UIF FOUJSF NPEVMF JT FYQPTFE BOE DBO CF JNQPSUFE
$)"15&3  5&45*/( 

CZ BOZ PUIFS NPEVMF *G ZPV XBOU UP FYQPSU FWFSZUIJOH JO B


NPEVMF UIFO TQFDJGZJOH FYQPSUT JT VOOFDFTTBSZ )PXFWFS JU
DBO IFMQ XIFO NBOBHJOH MBSHF QSPKFDUT UP TQFDJGZ XIBU XJMM
HFU VTFE CZ BOPUIFS NPEVMF BOE CZ FYDMVTJPO XIBU XJMM OPU

BT B XBZ PG EPDVNFOUJOH ZPVS JOUFOU *O UIJT DBTF XF IBWF


FYQPSUFE IFSF NPSF UIBO XF JNQPSUFE JOUP Main BT XF SFBMJ[FE
UIBU XF POMZ OFFEFE UIF UXP TQFDJƶFE GVODUJPOT GPS Main 8F
DPVME HP CBDL BOE SFNPWF UIF UIJOHT XF EJEOƊU TQFDJƶDBMMZ
JNQPSU GSPN UIF BCPWF FYQPSU MJTU CVU XF IBWFOƊU OPX UP HJWF
ZPV BO JEFB PG UIF QSPDFTT XFƊSF HPJOH UISPVHI QVUUJOH PVS
QSPKFDU UPHFUIFS

5VSOJOH XPSET JOUP DPEF


8F BSF BMTP VTJOH B RVBMJƶFE JNQPSU PG Data.Map 8F DPWFSFE
UIJT UZQF PG JNQPSU TPNFXIBU JO UIF QSFWJPVT DIBQUFS 8F
RVBMJGZ UIF JNQPSU BOE OBNF JU Ԃ TP UIBU XF DBO VTF UIBU Ԃ
BT B QSFƶY GPS UIF GVODUJPOT XFƊSF VTJOH GSPN UIBU QBDLBHF
5IBU XJMM IFMQ VT LFFQ USBDL PG XIFSF UIF GVODUJPOT DBNF GSPN
BOE BMTP BWPJE TBNFOBNF DMBTIFT XJUI 1SFMVEF GVODUJPOT CVU
XJUIPVU SFRVJSJOH VT UP UFEJPVTMZ UZQF Data.Map BT B QSFƶY UP
FBDI GVODUJPO OBNF
8FƊMM UBML NPSF BCPVU .BQ BT B EBUB TUSVDUVSF MBUFS JO UIF
CPPL 'PS OPX XF DBO VOEFSTUBOE JU BT CFJOH B CBMBODFE CJOBSZ
USFF XIFSF FBDI OPEF JT B QBJSJOH PG B LFZ BOE B WBMVF 5IF
LFZ JT BO JOEFY GPS UIF WBMVF ƈ B NBSLFS PG IPX UP ƶOE UIF
$)"15&3  5&45*/( 

WBMVF JO UIF USFF 5IF LFZ NVTU CF PSEFSBCMF UIBU JT NVTU IBWF
BO Ord JOTUBODF
KVTU BT PVS CJOBSZ USFF GVODUJPOT FBSMJFS TVDI
BT insert OFFEFE BO Ord JOTUBODF .BQT DBO CF NPSF FƸDJFOU
UIBO MJTUT CFDBVTF ZPV EP OPU IBWF UP TFBSDI MJOFBSMZ UISPVHI
B CVODI PG EBUB #FDBVTF UIF LFZT BSF PSEFSFE BOE UIF USFF JT
CBMBODFE TFBSDIJOH UISPVHI UIF CJOBSZ USFF EJWJEFT UIF TFBSDI
TQBDF JO IBMG FBDI UJNF ZPV HP ƌMFǒƍ PS ƌSJHIUƍ :PV DPNQBSF
UIF LFZ UP UIF JOEFY PG UIF DVSSFOU OPEF UP EFUFSNJOF JG ZPV
OFFE UP HP MFǒ MFTT
SJHIU HSFBUFS
PS JG ZPVƊWF BSSJWFE BU UIF
OPEF GPS ZPVS WBMVF FRVBM

:PV DBO TFF CFMPX XIZ XF VTFE B .BQ JOTUFBE PG B TJNQMF
MJTU 8F XBOU UP NBLF B MJTU PG QBJST XIFSF FBDI QBJS JODMVEFT
CPUI UIF &OHMJTIMBOHVBHF DIBSBDUFS BOE JUT .PSTF DPEF SFQ
SFTFOUBUJPO 8F EFƶOF PVS USBOTMJUFSBUJPO UBCMF UIVT

letterToMorse :: (M.Map Char Morse)


letterToMorse = M.fromList [
('a', ".-")
, ('b', "-...")
, ('c', "-.-.")
, ('d', "-..")
, ('e', ".")
$)"15&3  5&45*/( 

, ('f', "..-.")
, ('g', "--.")
, ('h', "....")
, ('i', "..")
, ('j', ".---")
, ('k', "-.-")

, ('l', ".-..")
, ('m', "--")
, ('n', "-.")
, ('o', "---")
, ('p', ".--.")
, ('q', "--.-")

, ('r', ".-.")
, ('s', "...")
, ('t', "-")
, ('u', "..-")
, ('v', "...-")
, ('w', ".--")

, ('x', "-..-")
, ('y', "-.--")
, ('z', "--..")
, ('1', ".----")
, ('2', "..---")
$)"15&3  5&45*/( 

, ('3', "...--")
, ('4', "....-")
, ('5', ".....")
, ('6', "-....")
, ('7', "--...")
, ('8', "---..")
, ('9', "----.")
, ('0', "-----")
]

/PUF UIBU XF VTFE M.fromList ƈ UIF Ԃ QSFƶY UFMMT VT UIJT


DPNFT GSPN Data.Map 8FƊSF VTJOH B .BQ UP BTTPDJBUF DIBSBDUFST
XJUI UIFJS .PSTF DPEF SFQSFTFOUBUJPOT letterToMorse JT UIF EFG
JOJUJPO PG UIF .BQ XFƊMM VTF UP MPPL VQ UIF NPSTF DPEFT GPS
JOEJWJEVBM DIBSBDUFST
/FYU XF XSJUF B GFX GVODUJPOT UIBU BMMPX VT UP DPOWFSU B
.PSTF DIBSBDUFS UP BO &OHMJTI DIBSBDUFS BOE WJDF WFSTB BOE
BMTP GVODUJPOT UP EP UIF TBNF GPS TUSJOHT
$)"15&3  5&45*/( 

morseToLetter :: M.Map Morse Char


morseToLetter =
M.foldWithKey (flip M.insert) M.empty
letterToMorse

charToMorse :: Char -> Maybe Morse


charToMorse c =
M.lookup c letterToMorse

stringToMorse :: String -> Maybe [Morse]


stringToMorse s =
sequence $ fmap charToMorse s

morseToChar :: Morse -> Maybe Char


morseToChar m =
M.lookup m morseToLetter

/PUJDF XF VTFE Maybe JO UISFF PG UIPTF OPU FWFSZ Char UIBU


DPVME QPUFOUJBMMZ PDDVS JO B String IBT B .PSTF SFQSFTFOUBUJPO

5IF .BJO FWFOU


/FYU XF XBOU UP TFU VQ B Main NPEVMF UIBU XJMM BDUVBMMZ IBOEMF
PVS .PSTF DPEF DPOWFSTJPOT /PUF UIBU JUƊT HPJOH UP JNQPSU B
CVODI PG UIJOHT TPNF PG XIJDI XF DPWFSFE JO UIF MBTU DIBQUFS
BOE TPNF XF IBWF OPU 4JODF XF XJMM OPU CF HPJOH JOUP UIF
$)"15&3  5&45*/( 

TQFDJƶDT PG IPX UIJT DPEF XPSLT XF XPOƊU EJTDVTT UIPTF JN


QPSUT IFSF *U JT IPXFWFS JNQPSUBOU UP OPUF UIBU POF PG PVS
JNQPSUT JT PVS Morse.hs NPEVMF GSPN BCPWF

-- src/Main.hs

module Main where

import Control.Monad (forever, when)


import Data.List (intercalate)
import Data.Traversable (traverse)
import Morse (stringToMorse, morseToChar)
import System.Environment (getArgs)
import System.Exit (exitFailure,
exitSuccess)
import System.IO (hGetLine, hIsEOF, stdin)

"T XF TBJE XFƊSF OPU HPJOH UP FYQMBJO UIJT QBSU JO EFUBJM


8F FODPVSBHF ZPV UP EP ZPVS CFTU SFBEJOH BOE JOUFSQSFUJOH
JU CVU JUƊT RVJUF EFOTF BOE UIJT DIBQUFS JTOƊU BCPVU UIJT DPEF
ƈ JUƊT BCPVU UIF UFTUT 8FƊSF DBSHPDVMUJOH B CJU IFSF XIJDI
XF EPOƊU MJLF UP EP CVU XFƊSF EPJOH JU TP UIBU XF DBO GPDVT PO
UIF UFTUJOH 5ZQF UIJT BMM JOUP ZPVS Main NPEVMF ƈ ƶSTU UIF
GVODUJPO UP DPOWFSU UP .PSTF
$)"15&3  5&45*/( 

convertToMorse :: IO ()
convertToMorse = forever $ do
weAreDone <- hIsEOF stdin
when weAreDone exitSuccess

-- otherwise, proceed.
line <- hGetLine stdin
convertLine line

where
convertLine line = do
let morse = stringToMorse line
case morse of
(Just str)
-> putStrLn
(intercalate " " str)
Nothing
-> do
putStrLn $ "ERROR: " ++ line
exitFailure

/PX BEE UIF GVODUJPO UP DPOWFSU GSPN .PSTF


$)"15&3  5&45*/( 

convertFromMorse :: IO ()
convertFromMorse = forever $ do
weAreDone <- hIsEOF stdin
when weAreDone exitSuccess

-- otherwise, proceed.
line <- hGetLine stdin
convertLine line

where
convertLine line = do
let decoded :: Maybe String
decoded =
traverse morseToChar
(words line)
case decoded of
(Just s) -> putStrLn s
Nothing -> do
putStrLn $ "ERROR: " ++ line
exitFailure

"OE OPX PVS PCMJHBUPSZ main GVODUJPO


$)"15&3  5&45*/( 

main :: IO ()
main = do
mode <- getArgs
case mode of
[arg] ->
case arg of
"from" -> convertFromMorse
"to" -> convertToMorse
_ -> argError
_ -> argError

where argError = do
putStrLn "Please specify the\
\ first argument\
\ as being 'from' or\
\ 'to' morse,\
\ such as: morse to"
exitFailure

.BLF TVSF JUƊT BMM XPSLJOH


0OF XBZ XF DBO NBLF TVSF FWFSZUIJOH JT XPSLJOH GPS VT GSPN
UIF DPNNBOE MJOF JT CZ VTJOH echo *G UIJT JT GBNJMJBS UP ZPV
BOE ZPV GFFM DPNGPSUBCMF XJUI UIJT HP BIFBE BOE USZ UIJT

$ echo "hi" | stack exec morse to


$)"15&3  5&45*/( 

.... ..

$ echo ".... .." | stack exec morse from


hi

*G ZPVƊE MJLF UP ƶOE PVU XIFSF 4UBDL QVU UIF FYFDVUBCMF ZPV
DBO VTF stack exec which morse PO .BD BOE -JOVY :PV DBO BMTP
VTF stack install UP BTL 4UBDL UP CVJME JG OFFEFE
BOE DPQZ UIF
CJOBSJFT GSPN ZPVS QSPKFDU JOUP B DPNNPO EJSFDUPSZ 0O .BD
BOE -JOVY UIBU XJMM CF .local/bin JO ZPVS IPNF EJSFDUPSZ 5IF
MPDBUJPO XBT DIPTFO QBSUMZ UP SFTQFDU 9%( HVJEFMJOFT
0UIFSXJTF KVTU MPBE UIJT NPEVMF JOUP ZPVS ()$J 3&1- BOE
HJWF JU B USZ UP FOTVSF FWFSZUIJOH DPNQJMFT BOE TFFNT UP CF JO
XPSLJOH PSEFS *UƊMM CF IFMQGVM UP ƶY BOZ UZQF PS TZOUBY FSSPST
OPX CFGPSF XF TUBSU USZJOH UP SVO UIF UFTUT

5JNF UP UFTU
/PX XF OFFE UP XSJUF PVS UFTU TVJUF 8F IBWF UIPTF JO UIFJS
PXO EJSFDUPSZ BOE ƶMF 8F XJMM BHBJO DBMM UIF NPEVMF Main
CVU OPUF UIF ƶMF OBNF UIF OBNF QFS TF JTOƊU JNQPSUBOU CVU
JU NVTU BHSFF XJUI UIF UFTU ƶMF ZPV IBWF OBNFE JO ZPVS DBCBM
DPOƶHVSBUJPO GPS UIJT QSPKFDU


https://wiki.archlinux.org/index.php/Xdg_user_directories
$)"15&3  5&45*/( 

-- tests/tests.hs

module Main where

import qualified Data.Map as M


import Morse
import Test.QuickCheck

8F IBWF NBOZ GFXFS JNQPSUT GPS UIJT XIJDI TIPVME BMM


BMSFBEZ CF GBNJMJBS UP ZPV
/PX XF TFU VQ PVS HFOFSBUPST GPS FOTVSJOH UIBU UIF SBOEPN
WBMVFT 2VJDL$IFDL VTFT UP UFTU PVS QSPHSBN BSF TFOTJCMF GPS
PVS .PSTF DPEF QSPHSBN

allowedChars :: [Char]
allowedChars = M.keys letterToMorse

allowedMorse :: [Morse]
allowedMorse = M.elems letterToMorse

charGen :: Gen Char


charGen = elements allowedChars

morseGen :: Gen Morse


morseGen = elements allowedMorse
$)"15&3  5&45*/( 

8F TBX elements CSJFƷZ BCPWF *U UBLFT B MJTU PG TPNF UZQF


ƈ JO UIFTF DBTFT PVS MJTUT PG BMMPXFE DIBSBDUFST BOE .PSTF
DIBSBDUFST ƈ BOE DIPPTFT B Gen WBMVF GSPN UIF WBMVFT JO UIBU
MJTU #FDBVTF Char JODMVEFT UIPVTBOET PG DIBSBDUFST UIBU IBWF
OP MFHJUJNBUF FRVJWBMFOU JO .PSTF DPEF XF OFFE UP XSJUF PVS
PXO DVTUPN HFOFSBUPST
/PX XF XSJUF VQ UIF QSPQFSUZ XF XBOU UP DIFDL 8F XBOU
UP DIFDL UIBU XIFO XF DPOWFSU TPNFUIJOH UP .PSTF DPEF BOE
UIFO CBDL BHBJO JU DPNFT PVU BT UIF TBNF TUSJOH XF TUBSUFE PVU
XJUI

prop_thereAndBackAgain :: Property
prop_thereAndBackAgain =
forAll charGen
(\c -> ((charToMorse c)
>>= morseToChar) == Just c)

main :: IO ()
main = quickCheck prop_thereAndBackAgain

5IJT JT IPX ZPVS TFUVQ TIPVME MPPL XIFO ZPV IBWF BMM UIJT
EPOF

$ tree
.
├── LICENSE
$)"15&3  5&45*/( 

├── Setup.hs
├── morse.cabal
├── src
│ ├── Main.hs
│ └── Morse.hs
├── stack.yaml
└── tests
└── tests.hs

5FTUJOH UIF .PSTF DPEF


/PX UIBU PVS DPOWFSTJPOT TFFN UP CF XPSLJOH MFUƊT SVO PVS
UFTUT UP NBLF TVSF 5IF QSPQFSUZ XFƊSF UFTUJOH JT UIBU XF HFU UIF
TBNF TUSJOH BǒFS XF DPOWFSU JU UP .PSTF BOE CBDL BHBJO -FUƊT
MPBE VQ PVS UFTUT CZ PQFOJOH B 3&1- GSPN PVS NBJO QSPKFDU
EJSFDUPSZ

$ stack ghci morse:tests

{... noise noise noise ...}

Ok, modules loaded: Main.


Prelude>

4XFFU 4UBDL MPBEFE FWFSZUIJOH GPS VT BOE FWFO CVJMU PVS


EFQFOEFODJFT JG OFFET CF -FUƊT TFF XIBU IBQQFOT
$)"15&3  5&45*/( 

*Main> main
+++ OK, passed 100 tests.

5IF UFTU HFOFSBUFT  SBOEPN .PSTF DPEF DPOWFSTJPOT


B CVODI PG SBOEPN TUSJOHT
BOE NBLFT TVSF UIFZ BSF BMXBZT
FRVBM PODF ZPV IBWF DPOWFSUFE UP BOE UIFO GSPN .PSTF DPEF
5IJT HJWFT ZPV B QSFUUZ TUSPOH BTTVSBODF UIBU ZPVS QSPHSBN JT
DPSSFDU BOE XJMM QFSGPSN BT FYQFDUFE GPS BOZ JOQVU WBMVF

 ,JDLJOH BSPVOE 2VJDL$IFDL


0OF PG UIF NPSF JNQPSUBOU QBSUT PG 2VJDL$IFDL JT MFBSOJOH UP
XSJUF JOTUBODFT PG UIF Arbitrary UZQFDMBTT GPS ZPVS EBUBUZQFT
*UƊT B TPNFXIBU VOGPSUVOBUF CVU TUJMM OFDFTTBSZ DPOWFOJFODF
GPS ZPVS DPEF UP JOUFHSBUF DMFBOMZ XJUI 2VJDL$IFDL DPEF *UƊT
JOJUJBMMZ B CJU DPOGVTJOH GPS CFHJOOFST CFDBVTF JU DPNQBDUT B
GFX EJƵFSFOU DPODFQUT BOE TPMVUJPOT UP QSPCMFNT JOUP B TJOHMF
UZQFDMBTT

#BCCZƊT 'JSTU "SCJUSBSZ


'JSTU XFƊMM CFHJO XJUI B NBYJNBMMZ TJNQMF Arbitrary JOTUBODF
GPS UIF Trivial EBUBUZQF
$)"15&3  5&45*/( 

module Main where

import Test.QuickCheck

data Trivial =
Trivial
deriving (Eq, Show)

trivialGen :: Gen Trivial


trivialGen =
return Trivial

instance Arbitrary Trivial where


arbitrary = trivialGen

5IF return JT OFDFTTBSZ UP SFUVSO Trivial JO UIF Gen NPOBE

main :: IO ()
main = do
sample trivialGen

-FUƊT UBLF B TBNQMF

Prelude> sample trivialGen


Trivial
Trivial
Trivial
$)"15&3  5&45*/( 

Trivial
Trivial
Trivial
Trivial
Trivial
Trivial
Trivial
Trivial

"MUIPVHI JUƊT JNQPTTJCMF UP TFF UIF QPJOU XJUI Trivial CZ JU


TFMG Gen WBMVFT BSF HFOFSBUPST PG SBOEPN WBMVFT UIBU 2VJDL$IFDL
VTFT UP HFU UFTU WBMVFT GSPN

*EFOUJUZ $SJTJT
5IJT POF JT B MJUUMF EJƵFSFOU *U XJMM QSPEVDF SBOEPN WBMVFT
FWFO JG UIF Identity TUSVDUVSF JUTFMG EPFTOƊU BOE DBOOPU WBSZ

data Identity a =
Identity a
deriving (Eq, Show)

identityGen :: Arbitrary a =>


Gen (Identity a)
identityGen = do
a <- arbitrary
return (Identity a)
$)"15&3  5&45*/( 

8FƊSF VTJOH UIF Gen NPOBE UP QMVDL B TJOHMF WBMVF PG UZQF


B PVU PG UIF BJS FNCFE JU JO Identity UIFO SFUVSO BT QBSU PG
UIF Gen NPOBE 8F LOPX UIJT JT XFJSE CVU JG ZPV EP JU UFO PS
UXFOUZ UJNFT ZPV NJHIU TUBSU UP MJLF JU
8FƊMM SFVTF UIF PSJHJOBM identityGen XF XSPUF 8F DBO NBLF
JU UIF EFGBVMU HFOFSBUPS GPS UIF Identity UZQF CZ NBLJOH JU UIF
arbitrary WBMVF JO UIF Arbitrary JOTUBODF

instance Arbitrary a =>


Arbitrary (Identity a) where
arbitrary = identityGen

identityGenInt :: Gen (Identity Int)


identityGenInt = identityGen

8FƊSF NBLJOH B HFOFSBUPS TVJUBCMF GPS TBNQMJOH CZ NBLJOH


UIF UZQF BSHVNFOU PG Identity VOBNCJHVPVT GPS UFTUJOH XJUI
UIF sample GVODUJPO :PVS PVUQVU JO UIF UFSNJOBM DPVME MPPL
TPNFUIJOH MJLF

Prelude> sample identityGenInt


Identity 0
Identity (-1)
Identity 2
Identity 4
Identity (-3)
$)"15&3  5&45*/( 

Identity 5
Identity 3
Identity (-1)
Identity 12
Identity 16
Identity 0

:PV TIPVME CF BCMF UP DIBOHF UIF DPODSFUF UZQF PG IdentityƊT


UZQF BSHVNFOU BOE HFOFSBUF EJƵFSFOU UZQFT PG TBNQMF WBMVFT

"SCJUSBSZ 1SPEVDUT
Arbitrary JOTUBODFT GPS QSPEVDU UZQFT HFU B UFFOTZ CJU NPSF
JOUFSFTUJOH CVU UIFZƊSF SFBMMZ BO FYUFOTJPO PG XIBU XF EJE GPS
Identity

data Pair a b =
Pair a b
deriving (Eq, Show)

pairGen :: (Arbitrary a,
Arbitrary b) =>
Gen (Pair a b)
pairGen = do
a <- arbitrary
b <- arbitrary
return (Pair a b)
$)"15&3  5&45*/( 

8F XJMM SFVTF PVS pairGen GVODUJPO BT UIF arbitrary WBMVF JO


UIF JOTUBODF

instance (Arbitrary a,
Arbitrary b) =>
Arbitrary (Pair a b) where
arbitrary = pairGen

pairGenIntString :: Gen (Pair Int String)


pairGenIntString = pairGen

"OE OPX XF DBO HFOFSBUF TPNF TBNQMF WBMVFT

Pair 0 ""
Pair (-2) ""
Pair (-3) "26"
Pair (-5) "B\NUL\143:\254\SO"
Pair (-6) "\184*\239\DC4"
Pair 5 "\238\213=J\NAK!"
Pair 6 "Pv$y"
Pair (-10) "G|J^"
Pair 16 "R"
Pair (-7) "("
Pair 19 "i\ETX]\182\ENQ"

"I UIF CFBVUZ PG SBOEPN 4USJOH WBMVFT


$)"15&3  5&45*/( 

(SFBUFS UIBO UIF TVN PG JUT QBSUT


8SJUJOH Arbitrary JOTUBODFT GPS TVN UZQFT JT B CJU NPSF JOUFS
FTUJOH TUJMM 'JSTU NBLF TVSF UIF GPMMPXJOH JT JODMVEFE JO ZPVS
JNQPSUT

import Test.QuickCheck.Gen (oneof)

4VN UZQFT SFQSFTFOU EJTKVODUJPO TP XJUI B TVN UZQF MJLF


Sum XF OFFE UP SFQSFTFOU UIF FYDMVTJWF QPTTJCJMJUJFT JO PVS Gen
0OF XBZ UP EP UIBU JT UP QVMM PVU BT NBOZ arbitrary WBMVFT
BT ZPV SFRVJSF GPS UIF DBTFT PG ZPVS TVN UZQF 8F IBWF UXP
EBUB DPOTUSVDUPST JO UIJT TVN UZQF TP XFƊMM XBOU UXP arbitrary
WBMVFT 5IFO XFƊMM SFQBDL UIFN JOUP Gen WBMVFT SFTVMUJOH JO B
WBMVF PG UZQF [Gen a] UIBU DBO CF QBTTFE UP oneof
$)"15&3  5&45*/( 

data Sum a b =
First a
| Second b
deriving (Eq, Show)

-- equal odds for each


sumGenEqual :: (Arbitrary a,
Arbitrary b) =>
Gen (Sum a b)
sumGenEqual = do
a <- arbitrary
b <- arbitrary
oneof [return $ First a,
return $ Second b]

5IF oneof GVODUJPO XJMM DSFBUF B Gen a GSPN B MJTU PG Gen a CZ


HJWJOH FBDI WBMVF BO FRVBM QSPCBCJMJUZ 'SPN UIFSF ZPVƊSF
EFMFHBUJOH UP UIF Arbitrary JOTUBODFT PG UIF UZQFT Ԑ BOE ԑ

sumGenCharInt :: Gen (Sum Char Int)


sumGenCharInt = sumGenEqual

8F TQFDJGZ XIJDI Arbitrary JOTUBODFT UP VTF GPS Ԑ BOE ԑ BOE


EP B UFTU SVO

Prelude> sample sumGenCharInt


$)"15&3  5&45*/( 

First 'P'
First '\227'
First '\238'
First '.'
Second (-3)
First '\132'
Second (-12)
Second (-12)
First '\186'
Second (-11)
First '\v'

8IFSF TVN UZQFT HFU FWFO NPSF JOUFSFTUJOH JT UIBU ZPV


DBO BDUVBMMZ DIPPTF B EJƵFSFOU XFJHIUJOH PG QSPCBCJMJUJFT UIBO
KVTU BO FRVBM EJTUSJCVUJPO $POTJEFS UIJT TOJQQFU PG UIF Maybe
Arbitrary JOTUBODF GSPN UIF 2VJDL$IFDL MJCSBSZ

instance Arbitrary a =>


Arbitrary (Maybe a) where
arbitrary =
frequency [(1, return Nothing),
(3, liftM Just arbitrary)]

*UƊT NBLJOH BO BSCJUSBSZ Just WBMVF UISFF UJNFT NPSF MJLFMZ


UIBO B Nothing WBMVF CFDBVTF UIF GPSNFS JT NPSF MJLFMZ UP CF
JOUFSFTUJOH BOE VTFGVM CVU ZPV TUJMM XBOU UP USZ TIBLJOH UIJOHT
PVU XJUI B Nothing GSPN UJNF UP UJNF
$)"15&3  5&45*/( 

"DDPSEJOHMZ XF DBO BTTJHO B  UJNFT IJHIFS QSPCBCJMJUZ UP


PVS First EBUB DPOTUSVDUPS JO B EJƵFSFOU Gen GPS Sum

sumGenFirstPls :: (Arbitrary a,
Arbitrary b) =>
Gen (Sum a b)
sumGenFirstPls = do
a <- arbitrary
b <- arbitrary
frequency [(10, return $ First a),
(1, return $ Second b)]

sumGenCharIntFirst :: Gen (Sum Char Int)


sumGenCharIntFirst = sumGenFirstPls

8JUI UIBU NPEJƶFE WFSTJPO ZPVƊMM ƶOE Second WBMVFT BSF


NVDI MFTT DPNNPO

First '\208'
First '\242'
First '\159'
First 'v'
First '\159'
First '\232'
First '3'
First 'l'
$)"15&3  5&45*/( 

Second (-16)
First 'x'
First 'Y'

0OF PG UIF LFZ JOTJHIUT IFSF JT UIBU UIF Arbitrary JOTUBODF


GPS B EBUBUZQF EPFTOƊU IBWF UP CF UIF POMZ XBZ UP HFOFSBUF PS
QSPWJEF SBOEPN WBMVFT PG ZPVS EBUBUZQF GPS 2VJDL$IFDL UFTUT
:PV DBO PƵFS BMUFSOBUJWF GenT GPS ZPVS UZQF XJUI JOUFSFTUJOH PS
VTFGVM CFIBWJPS BT XFMM

$P"SCJUSBSZ
CoArbitrary JT B DPVOUFSQBSU UP Arbitrary UIBU FOBCMFT UIF HFOFS
BUJPO PG GVODUJPOT ƶUUJOH B QBSUJDVMBS UZQF 3BUIFS UIBO UBMLJOH
BCPVU SBOEPN WBMVFT ZPV DBO HFU WJB Gen JU MFUT ZPV QSPWJEF
GVODUJPOT XJUI B WBMVF PG UZQF Ԑ BT BO BSHVNFOU JO PSEFS UP
WBSZ B Gen

arbitrary :: Arbitrary a =>


Gen a

coarbitrary :: CoArbitrary a =>


a -> Gen b -> Gen b
-- [1] [ 2 ] [ 3 ]

)FSF [1] JT VTFE UP SFUVSO B NPEJƶDBUJPO PS WBSJBOU PG [2]


XIJDI JT UIF SFTVMU [3] BU UIF FOE
$)"15&3  5&45*/( 

*U UVSOT PVU BT MPOH BT ZPVS EBUBUZQF IBT B Generic JOTUBODF


EFSJWFE ZPV DBO HFU UIFTF JOTUBODFT GPS GSFF 5IF GPMMPXJOH
TIPVME XPSL KVTU ƶOF

{-# LANGUAGE DeriveGeneric #-}

module CoArbitrary where

import GHC.Generics
import Test.QuickCheck

data Bool' =
True'
| False'
deriving (Generic)

instance CoArbitrary Bool'

5IJTƊMM UIFO MFU ZPV EP UIJOHT MJLF UIF GPMMPXJOH


$)"15&3  5&45*/( 

import Test.QuickCheck

-- plus the above

trueGen :: Gen Int


trueGen = coarbitrary True' arbitrary

falseGen :: Gen Int


falseGen = coarbitrary False' arbitrary

&TTFOUJBMMZ UIJT MFUT ZPV SBOEPNMZ HFOFSBUF B GVODUJPO *U


NJHIU CF B MJUUMF IBSE UP TFF XIZ ZPVƊE DBSF GPS OPX CVU JG
ZPV FWFS ƶOE ZPVSTFMG XBOUJOH UP SBOEPNMZ HFOFSBUF BOZUIJOH
XJUI UIF (->) UZQF JOTJEF JU TPNFXIFSF JU CFDPNFT TBMJFOU JO B
IVSSZ

 $IBQUFS &YFSDJTFT


/PX JUƊT UJNF UP XSJUF TPNF UFTUT PG ZPVS PXO :PV DPVME XSJUF
UFTUT GPS NPTU PG UIF FYFSDJTFT ZPVƊWF EPOF JO UIF CPPL CVU
XIFUIFS ZPVƊE XBOU UP VTF )TQFD PS 2VJDL$IFDL EFQFOET PO
XIBU ZPVƊSF USZJOH UP UFTU 8FƊWF USJFE UP TJNQMJGZ UIJOHT B CJU
CZ UFMMJOH ZPV XIJDI UP VTF GPS UIFTF FYFSDJTFT CVU BT BMXBZT
XF FODPVSBHF ZPV UP FYQFSJNFOU PO ZPVS PXO
$)"15&3  5&45*/( 

7BMJEBUJOH OVNCFST JOUP XPSET


3FNFNCFS UIF ƌOVNCFST JOUP XPSETƍ FYFSDJTF JO 3FDVSTJPO
:PVƊMM CF XSJUJOH UFTUT UP WBMJEBUF UIF GVODUJPOT ZPV XSPUF
$)"15&3  5&45*/( 

module WordNumberTest where

import Test.Hspec
import WordNumber (digitToWord, digits, wordNumber)

main :: IO ()
main = hspec $ do
describe "digitToWord" $ do
it "returns zero for 0" $ do
digitToWord 0 `shouldBe` "zero"
it "returns one for 1" $ do
print "???"

describe "digits" $ do
it "returns [1] for 1" $ do
digits 1 `shouldBe` [1]
it "returns [1, 0, 0] for 100" $ do
print "???"

describe "wordNumber" $ do
it "one-zero-zero given 100" $ do
wordNumber 100
`shouldBe` "one-zero-zero"
it "nine-zero-zero-one for 9001" $ do
print "???"
$)"15&3  5&45*/( 

'JMM JO UIF UFTU DBTFT UIBU QSJOU RVFTUJPO NBSLT *G ZPV UIJOL
PG BEEJUJPOBM UFTUT ZPV DPVME QFSGPSN BEE UIFN

6TJOH 2VJDL$IFDL
5FTU TPNF TJNQMF BSJUINFUJD QSPQFSUJFT VTJOH 2VJDL$IFDL

 -- for a function
half x = x / 2

-- this property should hold


halfIdentity = (*2) . half

 import Data.List (sort)

-- for any list you apply sort to


-- this property should hold
listOrdered :: (Ord a) => [a] -> Bool
listOrdered xs =
snd $ foldr go (Nothing, True) xs
where go _ status@(_, False) = status
go y (Nothing, t) = (Just y, t)
go y (Just x, t) = (Just y, x >= y)

 /PX XFƊMM UFTU UIF BTTPDJBUJWF BOE DPNNVUBUJWF QSPQFSUJFT


PG BEEJUJPO
$)"15&3  5&45*/( 

plusAssociative x y z =
x + (y + z) == (x + y) + z
plusCommutative x y =
x + y == y + x

 /PX EP UIF TBNF GPS NVMUJQMJDBUJPO

 8F NFOUJPOFE JO POF PG UIF ƶSTU DIBQUFST UIBU UIFSF BSF


TPNF MBXT JOWPMWJOH UIF SFMBUJPOTIJQ PG quot BOE rem BOE
div BOE mod 8SJUF 2VJDL$IFDL UFTUT UP QSPWF UIFN

-- quot rem
(quot x y)*y + (rem x y) == x

(div x y)*y + (mod x y) == x

 *T ?
BTTPDJBUJWF *T JU DPNNVUBUJWF 6TF 2VJDL$IFDL UP
TFF JG UIF DPNQVUFS DBO DPOUSBEJDU TVDI BO BTTFSUJPO

 5FTU UIBU SFWFSTJOH B MJTU UXJDF JT UIF TBNF BT UIF JEFOUJUZ


PG UIF MJTU

reverse . reverse == id

 8SJUF B QSPQFSUZ GPS UIF EFƶOJUJPO PG 




f $ a = f a

f . g = \x -> f (g x)
$)"15&3  5&45*/( 

 4FF JG UIFTF UXP GVODUJPOT BSF FRVBM

foldr (:) == (++)

foldr (++) [] == concat

 )N *T UIBU TP

f n xs = length (take n xs) == n

 'JOBMMZ UIJT JT B GVO POF :PV NBZ SFNFNCFS XF IBE ZPV
DPNQPTF read BOE show POF UJNF UP DPNQMFUF B ƌSPVOE
USJQƍ 8FMM OPX ZPV DBO UFTU UIBU JU XPSLT

f x = (read (show x)) == x

'BJMVSF

'JOE PVU XIZ UIJT QSPQFSUZ GBJMT

-- for a function
square x = x * x

-- why does this property not hold? Examine the type of sqrt.
squareIdentity = square . sqrt

)JOU 3FBE BCPVU ƷPBUJOH QPJOU BSJUINFUJD BOE QSFDJTJPO JG


ZPVƊSF VOGBNJMJBS XJUI JU
$)"15&3  5&45*/( 

*EFNQPUFODF
*EFNQPUFODF SFGFST UP B QSPQFSUZ PG TPNF GVODUJPOT JO XIJDI
UIF SFTVMU WBMVF EPFT OPU DIBOHF CFZPOE UIF JOJUJBM BQQMJDBUJPO
*G ZPV BQQMZ UIF GVODUJPO PODF JU SFUVSOT B SFTVMU BOE BQQMZJOH
UIF TBNF GVODUJPO UP UIBU WBMVF XPOƊU FWFS DIBOHF JU :PV NJHIU
UIJOL PG B MJTU UIBU ZPV TPSU PODF ZPV TPSU JU UIF TPSUFE MJTU XJMM
SFNBJO UIF TBNF BǒFS BQQMZJOH UIF TBNF TPSUJOH GVODUJPO UP
JU *UƊT BMSFBEZ TPSUFE TP OFX BQQMJDBUJPOT PG UIF TPSU GVODUJPO
XPOƊU DIBOHF JU
6TF 2VJDL$IFDL BOE UIF GPMMPXJOH IFMQFS GVODUJPOT UP EFNPO
TUSBUF JEFNQPUFODF GPS UIF GPMMPXJOH

twice f = f . f
fourTimes = twice . twice

 f x =
(capitalizeWord x
== twice capitalizeWord x)
== fourTimes capitalizeWord x

 f x =
(sort x
== twice sort x)
== fourTimes sort x
$)"15&3  5&45*/( 

.BLF B (FO SBOEPN HFOFSBUPS GPS UIF EBUBUZQF


8F EFNPOTUSBUFE JO UIF DIBQUFS IPX UP NBLF Gen HFOFSBUPST
GPS EJƵFSFOU EBUBUZQFT 8F BSF TP DFSUBJO ZPV FOKPZFE UIBU XF
BSF HPJOH UP BTL ZPV UP EP JU GPS TPNF OFX EBUBUZQFT

 &RVBM QSPCBCJMJUJFT GPS FBDI

data Fool =
Fulse
| Frue
deriving (Eq, Show)

 T DIBODF PG 'VMTF  DIBODF PG 'SVF

data Fool =
Fulse
| Frue
deriving (Eq, Show)

)BOHNBO UFTUJOH
/FYU ZPV TIPVME HP CBDL UP UIF )BOHNBO QSPKFDU GSPN UIF
QSFWJPVT DIBQUFS BOE XSJUF UFTUT 5IF LJOET PG UFTUT ZPV DBO
XSJUF BU UIJT QPJOU XJMM CF MJNJUFE EVF UP UIF JOUFSBDUJWF OBUVSF
PG UIF HBNF )PXFWFS ZPV DBO UFTU UIF GVODUJPOT 'PDVT ZPVS
BUUFOUJPO PO UFTUJOH UIF GPMMPXJOH
$)"15&3  5&45*/( 

fillInCharacter :: Puzzle -> Char -> Puzzle


fillInCharacter (Puzzle word
filledInSoFar s) c =
Puzzle word newFilledInSoFar (c : s)
where zipper guessed wordChar guessChar =
if wordChar == guessed
then Just wordChar
else guessChar
newFilledInSoFar =
let zd = (zipper c)
in zipWith zd word filledInSoFar

BOE
$)"15&3  5&45*/( 

handleGuess :: Puzzle -> Char -> IO Puzzle


handleGuess puzzle guess = do
putStrLn $ "Your guess was: " ++ [guess]
case (charInWord puzzle guess
, alreadyGuessed puzzle guess) of
(_, True) -> do
putStrLn "You already guessed that\
\ character, pick\
\ something else!"
return puzzle
(True, _) -> do
putStrLn "This character was in the\
\ word, filling in the\
\ word accordingly"
return (fillInCharacter puzzle guess)
(False, _) -> do
putStrLn "This character wasn't in\
\ the word, try again."
return (fillInCharacter puzzle guess)

3FGSFTI ZPVS NFNPSZ PO XIBU UIPTF BSF TVQQPTFE UP EP


BOE UIFO UFTU UP NBLF TVSF UIFZ EP
$)"15&3  5&45*/( 

7BMJEBUJOH DJQIFST
"T B ƶOBM FYFSDJTF DSFBUF 2VJDL$IFDL QSPQFSUJFT UIBU WFSJGZ
ZPVS $BFTBS BOE 7JHFO¨SF DJQIFST SFUVSO UIF TBNF EBUB BǒFS
FODPEJOH BOE EFDPEJOH B TUSJOH

 %FƶOJUJPOT
 6OJU UFTUJOH JT B NFUIPE JO XIJDI ZPV UFTU UIF TNBMMFTU
QBSUT PG BO BQQMJDBUJPO QPTTJCMF 5IFTF VOJUT BSF JOEJWJEV
BMMZ BOE JOEFQFOEFOUMZ TDSVUJOJ[FE GPS EFTJSFE CFIBWJPST
6OJU UFTUJOH JT CFUUFS BVUPNBUFE CVU JU DBO BMTP CF EPOF
NBOVBMMZ WJB B IVNBO FOUFSJOH JOQVUT BOE WFSJGZJOH PVU
QVUT

 1SPQFSUZ UFTUJOH JT B UFTUJOH NFUIPE XIFSF B TVCTFU PG B


MBSHF JOQVU TQBDF JT WBMJEBUFE VTVBMMZ BHBJOTU B QSPQFSUZ
PS MBX TPNF DPEF TIPVME BCJEF CZ *O )BTLFMM UIJT JT VTV
BMMZ EPOF XJUI 2VJDL$IFDL XIJDI GBDJMJUBUFT UIF SBOEPN
HFOFSBUJPO PG JOQVU BOE EFƶOJUJPO PG QSPQFSUJFT UP CF WFSJ
ƶFE $PNNPO QSPQFSUJFT UIBU BSF DIFDLFE VTJOH QSPQFSUZ
UFTUJOH BSF UIJOHT MJLF JEFOUJUZ BTTPDJBUJWJUZ JTPNPSQIJTN
BOE JEFNQPUFODF

 8IFO XF TBZ BO PQFSBUJPO PS GVODUJPO JT JEFNQPUFOU PS


TBUJTƶFT JEFNQPUFODF XF NFBO UIBU BQQMZJOH JU NVMUJQMF
UJNFT EPFTOƊU QSPEVDF B EJƵFSFOU SFTVMU GSPN UIF ƶSTU UJNF
$)"15&3  5&45*/( 

0OF FYBNQMF JT NVMUJQMZJOH CZ POF PS [FSP :PV BMXBZT


HFU UIF TBNF SFTVMU BT UIF ƶSTU UJNF ZPV NVMUJQMFE CZ POF
PS [FSP

 'PMMPXVQ SFTPVSDFT


 1FESP 7BTDPODFMPT "O JOUSPEVDUJPO UP 2VJDL$IFDL
UFTUJOH
https://www.fpcomplete.com/user/pbv/
an-introduction-to-quickcheck-testing

 ,PFO $MBFTTFO BOE +PIO )VHIFT 

2VJDL$IFDL " -JHIUXFJHIU 5PPM GPS 3BOEPN 5FTUJOH PG


)BTLFMM 1SPHSBNT

 1FESP 7BTDPODFMPT 7FSJGZJOH B 4JNQMF $PNQJMFS 6TJOH


1SPQFSUZCBTFE 3BOEPN 5FTUJOH
http://www.dcc.fc.up.pt/dcc/Pubs/TReports/TR13/
dcc-2013-06.pdf
$IBQUFS 

.POPJE 4FNJHSPVQ

4JNQMJDJUZ EPFT OPU


QSFDFEF DPNQMFYJUZ CVU
GPMMPXT JU

"MBO 1FSMJT


$)"15&3  .0/0*% 4&.*(3061 

 .POPJET BOE TFNJHSPVQT


0OF PG UIF ƶOFS QPJOUT PG UIF )BTLFMM DPNNVOJUZ IBT CFFO
JUT QSPQFOTJUZ GPS SFDPHOJ[JOH BCTUSBDU QBUUFSOT JO DPEF XIJDI
IBWF XFMMEFƶOFE MBXGVM SFQSFTFOUBUJPOT JO NBUIFNBUJDT "
XPSE GSFRVFOUMZ VTFE UP EFTDSJCF UIFTF BCTUSBDUJPOT JT BMHFCSB
CZ XIJDI XF NFBO POF PS NPSF PQFSBUJPOT BOE UIF TFU UIFZ
PQFSBUF PWFS #Z TFU XF NFBO UIF UZQF UIFZ PQFSBUF PWFS
0WFS UIF OFYU GFX DIBQUFST XFƊSF HPJOH UP CF MPPLJOH BU TPNF
PG UIFTF 4PNF ZPV NBZ IBWF IFBSE PG TVDI BT GVODUPS BOE
NPOBE 4PNF TVDI BT NPOPJE BOE UIF IVNCMF TFNJHSPVQ
NBZ TFFN OFX UP ZPV 0OF PG UIF UIJOHT UIBU )BTLFMM JT SFBMMZ
HPPE BU BSF UIFTF BMHFCSBT BOE JUƊT JNQPSUBOU UP NBTUFS UIFN
CFGPSF XF DBO EP TPNF PG UIF FYDJUJOH TUVƵ UIBUƊT DPNJOH
5IJT DIBQUFS XJMM JODMVEF

Ƒ "MHFCSBT

Ƒ -BXT

Ƒ .POPJET

Ƒ 4FNJHSPVQT
$)"15&3  .0/0*% 4&.*(3061 

 8IBU XF UBML BCPVU XIFO XF UBML


BCPVU BMHFCSBT
'PS TPNF PG VT UBMLJOH BCPVU ƌBO BMHFCSBƍ NBZ TPVOE TPNF
XIBU GPSFJHO 4P MFUƊT UBLF B TFDPOE BOE UBML BCPVU XIBU XFƊSF
UBMLJOH BCPVU XIFO XF VTF UIJT QISBTF BU MFBTU XIFO XFƊSF
UBMLJOH BCPVU )BTLFMM
Ɖ"MHFCSBƊ HFOFSBMMZ SFGFST UP POF PG UIF NPTU JNQPSUBOU ƶFMET
PG NBUIFNBUJDT *O UIJT VTBHF JU NFBOT UIF TUVEZ PG NBUIF
NBUJDBM TZNCPMT BOE UIF SVMFT HPWFSOJOH UIFJS NBOJQVMBUJPO
*U JT EJƵFSFOUJBUFE GSPN BSJUINFUJD CZ JUT VTF PG BCTUSBDUJPOT
TVDI BT WBSJBCMFT #Z UIF VTF PG WBSJBCMFT XFƊSF TBZJOH XF EPOƊU
DBSF NVDI BCPVU XIBU WBMVF XJMM CF QVU JOUP UIBU TMPU 8F
DBSF BCPVU UIF SVMFT PG IPX UP NBOJQVMBUF UIJT UIJOH XJUIPVU
SFGFSFODF UP JUT QBSUJDVMBS WBMVF
"OE TP BT XF TBJE BCPWF ƌBO BMHFCSBƍ SFGFST UP TPNF PQFSB
UJPOT BOE UIF TFU UIFZ PQFSBUF PWFS )FSF BHBJO XF DBSF MFTT
BCPVU UIF QBSUJDVMBST PG UIF WBMVFT PS EBUB XFƊSF XPSLJOH XJUI
BOE NPSF BCPVU UIF HFOFSBM SVMFT PG UIFJS VTF
*O )BTLFMM UIFTF BMHFCSBT DBO CF JNQMFNFOUFE XJUI UZQF
DMBTTFT UIF UZQFDMBTTFT EFƶOF UIF TFU PG PQFSBUJPOT 8IFO XF
UBML BCPVU PQFSBUJPOT PWFS B TFU UIF TFU JT UIF UZQF UIF PQFSB
UJPOT BSF GPS 5IF JOTUBODF EFƶOFT IPX FBDI PQFSBUJPO XJMM
QFSGPSN GPS B HJWFO UZQF PS TFU 0OF PG UIPTF BMHFCSBT XF VTF
JO )BTLFMM JT .POPJE *G ZPVƊSF B XPSLJOH QSPHSBNNFS ZPVƊWF
$)"15&3  .0/0*% 4&.*(3061 

QSPCBCMZ IBE NPOPJEBM QBUUFSOT JO ZPVS DPEF BMSFBEZ QFSIBQT


XJUIPVU SFBMJ[JOH JU

 .POPJE
" NPOPJE JT B CJOBSZ BTTPDJBUJWF PQFSBUJPO XJUI BO JEFOUJUZ
5IJT EFƶOJUJPO BMPOF UFMMT ZPV B MPU JG ZPVƊSF BDDVTUPNFE UP
QJDLJOH BQBSU NBUIFNBUJDBM EFƶOJUJPOT -FU VT EJTTFDU UIJT
GSPH

A monoid is a binary associative operation with an identity.


[1] [2] [3] [4] [5]

 5IF UIJOH XFƊSF UBMLJOH BCPVU ƈ NPOPJET 5IBUƊMM FOE VQ


CFJOH UIF OBNF PG PVS UZQFDMBTT

 #JOBSZ JF UXP 4P UIFSF XJMM CF UXP PG TPNFUIJOH

 "TTPDJBUJWF ƈ UIJT JT B QSPQFSUZ PS MBX UIBU NVTU CF TBUJT


ƶFE :PVƊWF TFFO BTTPDJBUJWJUZ XJUI BEEJUJPO BOE NVMUJQMJ
DBUJPO 8FƊMM FYQMBJO JU NPSF JO B NPNFOU

 0QFSBUJPO ƈ TP DBMMFE CFDBVTF JO NBUIFNBUJDT JUƊT VTVBMMZ


VTFE BT BO JOƶY PQFSBUPS :PV DBO SFBE UIJT JOUFSDIBOHF
BCMZ BT ƌGVODUJPOƍ /PUF UIBU HJWFO UIF NFOUJPO PG ƌCJOBSZƍ
FBSMJFS XF LOPX UIBU UIJT JT B GVODUJPO PG UXP BSHVNFOUT
$)"15&3  .0/0*% 4&.*(3061 

 *EFOUJUZ JT POF PG UIPTF XPSET JO NBUIFNBUJDT UIBU QPQT


VQ B MPU *O UIJT DPOUFYU XF DBO UBLF UIJT UP NFBO UIFSFƊMM
CF TPNF WBMVF XIJDI XIFO DPNCJOFE XJUI BOZ PUIFS
WBMVF XJMM BMXBZT SFUVSO UIBU PUIFS WBMVF 5IJT DBO CF
TFFO NPTU JNNFEJBUFMZ XJUI FYBNQMFT PS SVMFT

-- [] = mempty, or the identity


-- mappend is the binary operation
-- to append, or join, two arguments
mappend [1..5] [] = [1..5]
mappend [] [1..5] = [1..5]

-- or, more generally

mappend x mempty = x
mappend mempty x = x

4P JO QMBJO &OHMJTI B NPOPJE JT B GVODUJPO UIBU UBLFT UXP


BSHVNFOUT BOE GPMMPXT UXP MBXT BTTPDJBUJWJUZ BOE JEFOUJUZ
"TTPDJBUJWJUZ NFBOT UIF BSHVNFOUT DBO CF SFHSPVQFE PS SF
QBSFOUIFTJ[FE PS SFBTTPDJBUFE
JO EJƵFSFOU PSEFST BOE HJWF UIF
TBNF SFTVMU BT JO BEEJUJPO *EFOUJUZ NFBOT UIFSF FYJTUT TPNF
WBMVF TVDI UIBU XIFO XF QBTT JU BT JOQVU UP PVS GVODUJPO UIF
PQFSBUJPO JT SFOEFSFE NPPU BOE UIF PUIFS WBMVF JT SFUVSOFE
TVDI BT XIFO XF BEE [FSP PS NVMUJQMZ CZ POF Monoid JT UIF
UZQFDMBTT UIBU HFOFSBMJ[FT UIFTF MBXT BDSPTT UZQFT
$)"15&3  .0/0*% 4&.*(3061 

 )PX .POPJE JT EFƶOFE JO )BTLFMM


5ZQFDMBTTFT HJWF VT B XBZ UP SFDPHOJ[F PSHBOJ[F BOE VTF DPN
NPO GVODUJPOBMJUJFT BOE QBUUFSOT BDSPTT UZQFT UIBU EJƵFS JO
TPNF XBZT CVU BMTP IBWF UIJOHT JO DPNNPO 4P XF SFDPHOJ[F
UIBU BMUIPVHI UIFSF BSF NBOZ UZQFT PG OVNCFST BMM PG UIFN
DBO CF BSHVNFOUT JO BEEJUJPO BOE UIFO XF NBLF BO BEEJUJPO
GVODUJPO BT QBSU PG UIF Num DMBTT UIBU BMM OVNCFST JNQMFNFOU
5IF Monoid UZQFDMBTT SFDPHOJ[FT BOE PSEFST B EJƵFSFOU QBU
UFSO UIBO Num CVU UIF HPBM JT TJNJMBS 5IF QBUUFSO PG Monoid JT
PVUMJOFE BCPWF UZQFT UIBU IBWF CJOBSZ GVODUJPOT UIBU MFU ZPV
KPJO UIJOHT UPHFUIFS JO BDDPSEBODF XJUI UIF MBXT PG BTTPDJB
UJWJUZ BMPOH XJUI BO JEFOUJUZ WBMVF UIBU XJMM SFUVSO UIF PUIFS
BSHVNFOU VONPEJƶFE 5IJT JT UIF QBUUFSO PG TVNNBUJPO NVM
UJQMJDBUJPO BOE MJTU DPODBUFOBUJPO BNPOH PUIFS UIJOHT 5IF
UZQFDMBTT BCTUSBDUT BOE HFOFSBMJ[FT UIF QBUUFSO TP UIBU ZPV XSJUF
DPEF JO UFSNT PG BOZ UZQF UIBU DBO CF NPOPJEBMMZ DPNCJOFE
*O )BTLFMM XF UIJOL PG UZQFT BT IBWJOH BO JOTUBODF PG B
UZQFDMBTT 8IFO XF SFQSFTFOU BCTUSBDU PQFSBUJPOT UIBU DBO CF
SFVTFE BDSPTT B TFU PG UZQFT XF VTVBMMZ SFQSFTFOU UIFN BT B
UZQFDMBTT
5IF UZQFDMBTT Monoid JT EFƶOFE
$)"15&3  .0/0*% 4&.*(3061 

class Monoid m where


mempty :: m
mappend :: m -> m -> m
mconcat :: [m] -> m
mconcat = foldr mappend mempty

mappend JT IPX BOZ UXP WBMVFT UIBU JOIBCJU ZPVS UZQF DBO CF
KPJOFE UPHFUIFS mempty JT UIF JEFOUJUZ WBMVF GPS UIBU mappend
PQFSBUJPO 5IFSF BSF TPNF MBXT UIBU BMM .POPJE JOTUBODFT
NVTU BCJEF BOE XFƊMM HFU UP UIPTF TPPO /FYU MFUƊT MPPL BU
TPNF FYBNQMFT PG NPOPJET JO BDUJPO

 &YBNQMFT PG VTJOH .POPJE


5IF OJDF UIJOH BCPVU .POPJE SFBMMZ JT UIBU UIFZ BSF RVJUF
GBNJMJBS UIFZƊSF BMM PWFS UIF QMBDF 5IF CFTU XBZ UP VOEFS
TUBOE UIFN JOJUJBMMZ JT UP MPPL BU FYBNQMFT PG TPNF DPNNPO
NPOPJEBM PQFSBUJPOT BOE SFNFNCFS UIBU UIJT UZQFDMBTT KVTU
BCTUSBDUT UIF QBUUFSO PVU HJWJOH ZPV UIF BCJMJUZ UP VTF UIF PQFS
BUJPOT PWFS B MBSHFS SBOHF PG UZQFT

-JTU
0OF PG UIF NPSF QFSWBTJWF UZQFT XJUI BO JOTUBODF PG Monoid JT
List $IFDL PVU IPX NPOPJEBM PQFSBUJPOT XPSL XJUI MJTUT

Prelude> mappend [1, 2, 3] [4, 5, 6]


$)"15&3  .0/0*% 4&.*(3061 

[1,2,3,4,5,6]
Prelude> mconcat [[1..3], [4..6]]
[1,2,3,4,5,6]
Prelude> mappend "Trout" " goes well with garlic"
"Trout goes well with garlic"

5IJT TIPVME MPPL GBNJMJBS CFDBVTF XFƊWF DFSUBJOMZ TFFO UIJT


CFGPSF

Prelude> (++) [1, 2, 3] [4, 5, 6]


[1,2,3,4,5,6]
Prelude> (++) "Trout" " goes well with garlic"
"Trout goes well with garlic"
Prelude> foldr (++) [] [[1..3], [4..6]]
[1,2,3,4,5,6]
Prelude> foldr mappend mempty [[1..3], [4..6]]
[1,2,3,4,5,6]

0VS PME GSJFOE (++) "OE JG XF MPPL BU UIF EFƶOJUJPO PG


Monoid GPS MJTUT XF DBO TFF IPX UIJT BMM MJOFT VQ

instance Monoid [a] where


mempty = []
mappend = (++)

'PS PUIFS UZQFT UIF JOTUBODFT XPVME CF EJƵFSFOU CVU UIF


JEFBT CFIJOE UIFN SFNBJO UIF TBNF
$)"15&3  .0/0*% 4&.*(3061 

 8IZ *OUFHFS EPFTOƊU IBWF B


.POPJE
5IF UZQF Integer EPFT OPU IBWF B Monoid JOTUBODF /POF PG UIF
OVNFSJD UZQFT EP :FU JUƊT DMFBS UIBU OVNCFST IBWF NPOPJEBM
PQFSBUJPOT TP XIBUƊT VQ XJUI UIBU )BTLFMM
8IJMF JO NBUIFNBUJDT UIF NPOPJE PG OVNCFST JT TVNNB
UJPO UIFSFƊT OPU B DMFBS SFBTPO XIZ JU DBOƊU CF NVMUJQMJDBUJPO
#PUI PQFSBUJPOT BSF NPOPJEBM CJOBSZ BTTPDJBUJWF IBWJOH BO
JEFOUJUZ WBMVF
CVU FBDI UZQF TIPVME POMZ IBWF POF VOJRVF
JOTUBODF GPS B HJWFO UZQFDMBTT OPU UXP POF JOTUBODF GPS B TVN
POF GPS B QSPEVDU

5IJT XPOƊU XPSL

Prelude> mappend 1 1

<interactive>:7:1:
No instance for (Num a0) arising from a use of ‘it’

...and a bunch of noise.

#FDBVTF JU JTOƊU DMFBS JG UIPTF TIPVME CF BEEFE PS NVMUJQMJFE


BT B mappend PQFSBUJPO *U TBZT UIFSFƊT OP Monoid GPS Num a => a
GPS UIBU SFBTPO :PV HFU UIF JEFB
5P SFTPMWF UIF DPOƷJDU XF IBWF UIF Sum BOE Product OFXUZQFT
UP XSBQ OVNFSJD WBMVFT BOE TJHOBM XIJDI .POPJE JOTUBODF XF
$)"15&3  .0/0*% 4&.*(3061 

XBOU 5IFTF OFXUZQFT BSF CVJMU JOUP UIF Monoid MJCSBSZ 8IJMF
UIFSF BSF UXP QPTTJCMF JOTUBODFT PG Monoid GPS OVNFSJD WBMVFT
XF BWPJE VTJOH TDPQJOH USJDLT BOE BCJEF CZ UIF SVMF UIBU UZQF
DMBTT JOTUBODFT BSF VOJRVF UP UIF UZQFT UIFZ BSF GPS

Prelude> mappend (Sum 1) (Sum 5)


Sum {getSum = 6}
Prelude> mappend (Product 5) (Product 5)
Product {getProduct = 25}
Prelude> mappend (Sum 4.5) (Sum 3.4)
Sum {getSum = 7.9}

/PUF UIBU XF DPVME VTF JU XJUI WBMVFT UIBU BSFOƊU JOUFHSBM


8F DBO VTF UIFTF .POPJE OFXUZQFT GPS BMM UIF UZQFT UIBU IBWF
JOTUBODFT PG Num
*OUFHFST GPSN B NPOPJE VOEFS TVNNBUJPO BOE NVMUJQMJDBUJPO 8F
DBO TJNJMBSMZ TBZ UIBU MJTUT GPSN B NPOPJE VOEFS DPODBUFOBUJPO
*UƊT XPSUI QPJOUJOH PVU IFSF UIBU OVNCFST BSFOƊU UIF POMZ
TFUT UIBU IBWF NPSF UIBO POF QPTTJCMF NPOPJE -JTUT IBWF
NPSF UIBO POF QPTTJCMF NPOPJE BMUIPVHI GPS OPX XFƊSF POMZ
XPSLJOH XJUI DPODBUFOBUJPO XFƊMM MPPL BU UIF PUIFS MJTU NPOPJE
JO BOPUIFS DIBQUFS
 4FWFSBM PUIFS UZQFT EP BT XFMM 8F VTVBMMZ
FOGPSDF UIF VOJRVF JOTUBODF SVMF CZ VTJOH newtype UP TFQBSBUF
UIF EJƵFSFOU NPOPJEBM CFIBWJPST
$)"15&3  .0/0*% 4&.*(3061 

8IZ OFXUZQF
6TF PG B newtype DBO CF IBSE UP KVTUJGZ PS FYQMBJO UP QFPQMF UIBU
EPOƊU ZFU IBWF HPPE JOUVJUJPOT GPS IPX )BTLFMM DPEF HFUT DPN
QJMFE BOE UIF SFQSFTFOUBUJPOT PG EBUB VTFE CZ ZPVS DPNQVUFS
JO UIF DPVSTF PG FYFDVUJOH ZPVS QSPHSBNT 8JUI UIBU JO NJOE
XFƊMM EP PVS CFTU BOE PƵFS UXP FYQMBOBUJPOT JOUFOEFE GPS UXP
EJƵFSFOU BVEJFODFT 8F XJMM SFUVSO UP UIF UPQJD PG newtype JO
NPSF EFUBJM MBUFS JO UIF CPPL
'JSTU UIFSFƊT OPU NVDI TFNBOUJD EJƵFSFODF FYDFQU GPS DJS
DVNTUBODFT JOWPMWJOH bottom FYQMBJOFE MBUFS
CFUXFFO UIF GPM
MPXJOH EBUBUZQFT

data Server = Server String

newtype Server' = Server' String

5IF NBJO EJƵFSFODFT BSF UIBU VTJOH newtype DPOTUSBJOT UIF


EBUBUZQF UP IBWJOH B TJOHMF VOBSZ EBUB DPOTUSVDUPS BOE newtype
HVBSBOUFFT OP BEEJUJPOBM SVOUJNF PWFSIFBE JO ƌXSBQQJOHƍ UIF
PSJHJOBM UZQF 5IBU JT UIF SVOUJNF SFQSFTFOUBUJPO PG newtype
BOE XIBU JU XSBQT BSF BMXBZT JEFOUJDBM ƈ OP BEEJUJPOBM ƌCPYJOH
VQƍ PG UIF EBUB BT JT OFDFTTBSZ GPS UZQJDBM QSPEVDUT BOE TVNT

'PS WFUFSBO QSPHSBNNFST UIBU VOEFSTUBOE QPJOUFST newtype


JT MJLF B TJOHMFNFNCFS $ VOJPO UIBU BWPJET DSFBUJOH BO FYUSB
QPJOUFS CVU TUJMM HJWFT ZPV B OFX UZQF DPOTUSVDUPS BOE EBUB
$)"15&3  .0/0*% 4&.*(3061 

DPOTUSVDUPS TP ZPV EPOƊU NJY VQ UIF NBOZ NBOZ NBOZ UIJOHT


UIBU TIBSF B TJOHMF SFQSFTFOUBUJPO

*O TVNNBSZ XIZ ZPV NJHIU VTF OFXUZQF

 4JHOBM JOUFOU VTJOH newtype NBLFT JU DMFBS UIBU ZPV POMZ


JOUFOE GPS JU UP CF B XSBQQFS GPS UIF VOEFSMZJOH UZQF 5IF
OFXUZQF DBOOPU FWFOUVBMMZ HSPX JOUP B NPSF DPNQMJDBUFE
TVN PS QSPEVDU UZQF XIJMF B OPSNBM EBUBUZQF DBO

 *NQSPWF UZQF TBGFUZ BWPJE NJYJOH VQ NBOZ WBMVFT PG UIF


TBNF SFQSFTFOUBUJPO TVDI BT Text PS Integer

 "EE EJƵFSFOU UZQFDMBTT JOTUBODFT UP B UZQF UIBU JT PUIFS


XJTF VODIBOHFE SFQSFTFOUBUJPOBMMZ TVDI BT XJUI Sum BOE
Product

.PSF PO 4VN BOE 1SPEVDU


5IFSFƊT NPSF UIBO POF WBMJE Monoid JOTUBODF POF DBO XSJUF GPS
OVNCFST TP XF VTF newtype XSBQQFST UP EJTUJOHVJTI XIJDI XF
XBOU *G ZPV JNQPSU Data.Monoid ZPVƊMM TFF UIF Sum BOE Product
EBUB DPOTUSVDUPST

Prelude> import Data.Monoid


Prelude> :info Sum
newtype Sum a = Sum {getSum :: a}
...some instances elided...
$)"15&3  .0/0*% 4&.*(3061 

instance Num a => Monoid (Sum a)

Prelude> :info Product


newtype Product a = Product {getProduct :: a}
...some instances elided...
instance Num a => Monoid (Product a)

5IF JOTUBODFT TBZ UIBU XF DBO VTF Sum PS Product WBMVFT BT B


Monoid BT MPOH BT UIFZ DPOUBJO OVNFSJD WBMVFT 8F DBO QSPWF
UIJT JT UIF DBTF GPS PVSTFMWFT 8FƊSF HPJOH UP CF VTJOH UIF JOƶY
PQFSBUPS GPS mappend JO UIFTF FYBNQMFT *U IBT UIF TBNF UZQF
BOE EPFT UIF TBNF UIJOH CVU TBWFT TPNF DIBSBDUFST BOE XJMM
NBLF UIFTF FYBNQMFT B CJU DMFBOFS

Prelude Control.Applicative Data.Monoid> :t (<>)


(<>) :: Monoid m => m -> m -> m

Prelude> Sum "Frank" <> Sum " " <> Sum "Herbert"

No instance for (Num [Char]) arising from a use of ‘<>’

5IF FYBNQMF EJEOƊU XPSL CFDBVTF UIF a JO Sum a XBT String


XIJDI JT OPU BO JOTUBODF PG Num
Sum BOE Product EP XIBU ZPVƊE FYQFDU XJUI KVTU B CJU PG TZO
UBDUJD TVSQSJTF

Prelude Data.Monoid> mappend (Sum 8) (Sum 9)


$)"15&3  .0/0*% 4&.*(3061 

Sum {getSum = 17}

Prelude Data.Monoid> mappend mempty Sum 9


Sum {getSum = 9}

#VU mappend POMZ KPJOT UXP UIJOHT TP ZPV DBOƊU EP UIJT

Prelude Data.Monoid> mappend (Sum 8) (Sum 9) (Sum 10)

:PVƊMM HFU B CJH FSSPS NFTTBHF JODMVEJOH UIJT MJOF

Possible cause: ‘Sum’ is applied to too many arguments


In the first argument of ‘mappend’, namely ‘(Sum 8)’

4P UIBUƊT FBTZ FOPVHI UP ƶY CZ OFTUJOH

Prelude> mappend (Sum 1) (mappend (Sum 2) (Sum 3))


Sum {getSum = 6}

0S TPNFXIBU MFTT UFEJPVT CZ JOƶYJOH UIF NBQQFOE GVOD


UJPO

Prelude> (Sum 1) <> (Sum 1) <> (Sum 1)


Sum {getSum = 3}
Prelude> (Sum 1) `mappend` (Sum 1) `mappend` (Sum 1)
Sum {getSum = 3}

0S ZPV DPVME BMTP QVU ZPVS SumT JO B MJTU BOE VTF mconcat
$)"15&3  .0/0*% 4&.*(3061 

Prelude Data.Monoid> mconcat [(Sum 8), (Sum 9), (Sum 10)]


Sum {getSum = 27}

%VF UP UIF TQFDJBM TZOUBY PG Sum BOE Product XF BMTP IBWF


CVJMUJO SFDPSE ƶFME BDDFTTPST XF DBO VTF UP VOXSBQ UIF WBMVF

Prelude> getSum $ mappend (Sum 1) (Sum 1)


2
Prelude> getProduct $ mappend (Product 5) (Product 5)
25
Prelude> getSum $ mconcat [(Sum 5), (Sum 6), (Sum 7)]
18

Product JT TJNJMBS UP Sum CVU GPS NVMUJQMJDBUJPO

 8IZ CPUIFS


#FDBVTF NPOPJET BSF SFBMMZ DPNNPO BOE UIFZƊSF B OJDF BC
TUSBDUJPO UP XPSL XJUI XIFO ZPV IBWF NVMUJQMF NPOPJEBM
UIJOHT SVOOJOH BSPVOE JO B QSPKFDU ,OPXJOH XIBU B NPOPJE
JT DBO IFMQ ZPV UP SFDPHOJ[F XIFO ZPVƊWF FODPVOUFSFE UIF QBU
UFSO 'VSUIFS IBWJOH QSJODJQMFE MBXT GPS JU NFBOT ZPV LOPX
ZPV DBO DPNCJOF NPOPJEBM PQFSBUJPOT TBGFMZ 8IFO XF TBZ
TPNFUIJOH ƌJTƍ B .POPJE PS DBO CF EFTDSJCFE BT NPOPJEBM XF
NFBO ZPV DBO EFƶOF BU MFBTU POF MBXBCJEJOH Monoid JOTUBODF
GPS JU
$)"15&3  .0/0*% 4&.*(3061 

" DPNNPO VTF PG NPOPJET JT UP TUSVDUVSF BOE EFTDSJCF DPN


NPO NPEFT PG QSPDFTTJOH EBUB 4PNFUJNFT UIJT JT UP EFTDSJCF
BO "1* GPS JODSFNFOUBMMZ QSPDFTTJOH B MBSHF EBUBTFU TPNFUJNFT
UP EFTDSJCF HVBSBOUFFT OFFEFE UP SPMM VQ BHHSFHBUJPOT UIJOL
TVNNBUJPO
JO B QBSBMMFM DPODVSSFOU PS EJTUSJCVUFE QSPDFTTJOH
GSBNFXPSL
0OF FYBNQMF PG XIFSF UIJOHT MJLF UIF JEFOUJUZ DBO CF VTFGVM
JT JG ZPV XBOU UP XSJUF B HFOFSJD MJCSBSZ GPS EPJOH XPSL JO
QBSBMMFM :PV DPVME DIPPTF UP EFTDSJCF ZPVS XPSL BT CFJOH MJLF
B USFF XJUI FBDI VOJU PG XPSL CFJOH B MFBG 'SPN UIFSF ZPV
DBO QBSUJUJPO UIF USFF JOUP BT NBOZ DIVOLT BT BSF OFDFTTBSZ UP
TBUVSBUF UIF OVNCFS PG QSPDFTTPS DPSFT PS FOUJSF DPNQVUFST
ZPV XBOU UP EFWPUF UP UIF XPSL 5IF QSPCMFN JT JG XF IBWF B
QBJSXJTF PQFSBUJPO BOE XF OFFE UP DPNCJOF BO PEE OVNCFS
PG MFBWFT IPX EP XF FWFO PVU UIF DPVOU
0OF TUSBJHIUGPSXBSE XBZ DPVME CF UP TJNQMZ QSPWJEF mempty
UIF JEFOUJUZ WBMVF
UP UIF PEE MFBWFT PVU TP XF HFU UIF TBNF
SFTVMU BOE QBTT JU VQ UP UIF OFYU MBZFS PG BHHSFHBUJPO
" WBSJBOU PG NPOPJE UIBU QSPWJEFT NPSF HVBSBOUFFT JT UIF
"CFMJBO PS DPNNVUBUJWF NPOPJE $PNNVUBUJWJUZ DBO CF QBS
UJDVMBSMZ IFMQGVM XIFO EPJOH DPODVSSFOU PS EJTUSJCVUFE QSP
DFTTJOH PG EBUB CFDBVTF JU NFBOT UIF JOUFSNFEJBUF SFTVMUT CFJOH
DPNQVUFE JO B EJƵFSFOU PSEFS XPOƊU DIBOHF UIF FWFOUVBM BO
TXFS
.POPJET BSF FWFO TUSPOHMZ BTTPDJBUFE XJUI UIF DPODFQU PG
GPMEJOH PS DBUBNPSQIJTN ƈ TPNFUIJOH XF EP BMM UIF UJNF JO
$)"15&3  .0/0*% 4&.*(3061 

)BTLFMM :PVƊMM TFF UIJT NPSF FYQMJDJUMZ JO UIF 'PMEBCMF DIBQUFS


CVU IFSFƊT B UBTUF

Prelude> foldr mappend mempty ([2, 4, 6] :: [Product Int])


Product {getProduct = 48}

Prelude> foldr mappend mempty ([2, 4, 6] :: [Sum Int])


Sum {getSum = 12}

Prelude> foldr mappend mempty ["blah", "woot"]


"blahwoot"

:PVƊMM TFF NPOPJEBM TUSVDUVSF DPNF VQ XIFO XF FYQMBJO


"QQMJDBUJWF BOE .POBE BT XFMM

 -BXT
8FƊMM HFU UP UIPTF MBXT JO B NPNFOU 'JSTU IFFE PVS MJUUMF DSJ EF
DPFVS BCPVU XIZ ZPV TIPVME DBSF BCPVU NBUIFNBUJDBM MBXT
-BXT DJSDVNTDSJCF XIBU DPOTUJUVUFT B WBMJE JOTUBODF PS DPO
DSFUF JOTUBODF PG UIF BMHFCSB PS TFU PG PQFSBUJPOT XFƊSF XPSLJOH
XJUI 8F DBSF BCPVU UIF MBXT B .POPJE NVTU BEIFSF UP CFDBVTF
NBUIFNBUJDJBOT DBSF BCPVU UIF MBXT 5IBU NBUUFST CFDBVTF
NBUIFNBUJDJBOT PǒFO XBOU UIF TBNF UIJOHT QSPHSBNNFST
XBOU " QSPPG UIBU JT JOFMFHBOU B QSPPG UFSN UIBU EPFTOƊU DPN
QPTF XFMM PS UIBU DBOOPU CF VOEFSTUPPE JT OPU WFSZ HPPE PS
$)"15&3  .0/0*% 4&.*(3061 

VTFGVM UP B NBUIFNBUJDJBO 1SPPGT BSF QSPHSBNT BOE QSPHSBNT


BSF QSPPGT 8F DBSF BCPVU QSPHSBNT UIBU DPNQPTF XFMM UIBU
BSF FBTZ UP VOEFSTUBOE BOE XIJDI IBWF QSFEJDUBCMF CFIBWJPS
5P UIBU FOE XF TIPVME TUFBM QSPMJƶDBMMZ GSPN NBUIFNBUJDT
"MHFCSBT BSF EFƶOFE CZ UIFJS MBXT BOE BSF VTFGVM QSJODJQBMMZ
GPS UIFJS MBXT -BXT NBLF VQ XIBU BMHFCSBT BSF
"NPOH PUIFS UIJOHT MBXT QSPWJEF VT HVBSBOUFFT UIBU MFU
VT CVJME PO TPMJE GPVOEBUJPOT 5IPTF HVBSBOUFFT HJWF VT QSF
EJDUBCMF DPNQPTJUJPO PS DPNCJOBUJPO
PG QSPHSBNT 8JUIPVU
UIF BCJMJUZ UP TBGFMZ DPNCJOF QSPHSBNT FWFSZUIJOH NVTU CF
IBOEXSJUUFO GSPN TDSBUDI OPUIJOH DPVME CF SFVTFE 5IF QIZT
JDBM XPSME IBT FOKPZFE UIF VTFGVM QSPQFSUJFT PG TUPOF TUBDLFE
VQ PO UPQ PG TUPOF TJODF UIF (SFBU 1ZSBNJE PG (J[B XBT CVJMU JO
UIF QIBSBPI 4OFGFSVƊT SFJHO JO   #$ 4JNJMBSMZ JG XF XBOU
UP CF BCMF UP TUBDL VQ GVODUJPOT TDBMBCMZ UIFZ OFFE UP PCFZ
MBXT 4UPOFT EPOƊU FWBQPSBUF JOUP UIJO BJS PS FYQMPEF WJPMFOUMZ
*UƊE CF OJDF JG PVS QSPHSBNT XFSF TJNJMBSMZ USVTUXPSUIZ
5IFSF BSF NPSF QPTTJCMF MBXT XF DBO SFRVJSF GPS BO BMHF
CSB UIBO KVTU BTTPDJBUJWJUZ PS BO JEFOUJUZ CVU UIFTF BSF TJNQMF
FYBNQMFT XF BSF TUBSUJOH XJUI GPS OPX QBSUMZ CFDBVTF Monoid
JT B HPPE QMBDF UP TUBSU XJUI BMHFCSBTBTUZQFDMBTTFT 8FƊMM TFF
FYBNQMFT PG NPSF MBUFS
Monoid JOTUBODFT NVTU BCJEF CZ UIF GPMMPXJOH MBXT
$)"15&3  .0/0*% 4&.*(3061 

-- left identity
mappend mempty x = x

-- right identity
mappend x mempty = x

-- associativity
mappend x (mappend y z) = mappend (mappend x y) z

mconcat = foldr mappend mempty

)FSF JT IPX UIF JEFOUJUZ MBX MPPLT JO QSBDUJDF

Prelude> import Data.Monoid

-- left identity
Prelude> mappend mempty (Sum 1)
Sum {getSum = 1}

-- right identity
Prelude> mappend (Sum 1) mempty
Sum {getSum = 1}

8F DBO EFNPOTUSBUF BTTPDJBUJWJUZ NPSF FBTJMZ JG XF ƶSTU


JOUSPEVDF UIF JOƶY PQFSBUPS GPS mappend <> /PUF UIF QBSFOUIF
TJ[BUJPO PO UIF UXP FYBNQMFT
$)"15&3  .0/0*% 4&.*(3061 

Prelude> :t (<>)
(<>) :: Monoid m => m -> m -> m

-- associativity
Prelude> (Sum 1) <> (Sum 2 <> Sum 3)
Sum {getSum = 6}

Prelude> (Sum 1 <> Sum 2) <> (Sum 3)


Sum {getSum = 6}

"OE mconcat TIPVME IBWF UIF TBNF SFTVMU BT foldr mappend


mempty

Prelude> mconcat [Sum 1, Sum 2, Sum 3]


Sum {getSum = 6}

Prelude> foldr mappend mempty [Sum 1, Sum 2, Sum 3]


Sum {getSum = 6}

/PX MFUƊT TFF BMM PG UIBU BHBJO CVU VTJOH UIF .POPJE PG MJTUT

-- mempty is []
-- mappend is (++)

-- left identity
Prelude> mappend mempty [1, 2, 3]
[1,2,3]
$)"15&3  .0/0*% 4&.*(3061 

-- right identity
Prelude> mappend [1, 2, 3] mempty
[1,2,3]

-- associativity
Prelude> [1] <> ([2] <> [3])
[1,2,3]

Prelude> ([1] <> [2]) <> [3]


[1,2,3]

-- mconcat ~ foldr mappend mempty


Prelude> mconcat [[1], [2], [3]]
[1,2,3]

Prelude> foldr mappend mempty [[1], [2], [3]]


[1,2,3]

Prelude> concat [[1], [2], [3]]


[1,2,3]

5IF JNQPSUBOU QBSU IFSF JT UIBU ZPV IBWF UIFTF HVBSBOUFFT


FWFO XIFO ZPV EPOƊU LOPX XIBU .POPJE ZPVƊMM CF XPSLJOH XJUI
$)"15&3  .0/0*% 4&.*(3061 

 %JƵFSFOU JOTUBODF TBNF


SFQSFTFOUBUJPO
.POPJE JT TPNFXIBU EJƵFSFOU GSPN PUIFS UZQFDMBTTFT JO )BTLFMM
JO UIBU NBOZ EBUBUZQFT IBWF NPSF UIBO POF WBMJE NPOPJE 8F
TBX UIBU GPS OVNCFST CPUI BEEJUJPO BOE NVMUJQMJDBUJPO BSF
TFOTJCMF NPOPJET XJUI EJƵFSFOU CFIBWJPST 8IFO XF IBWF
NPSF UIBO POF QPUFOUJBM JNQMFNFOUBUJPO GPS .POPJE GPS B
EBUBUZQF JUƊT NPTU DPOWFOJFOU UP VTF OFXUZQFT UP UFMM UIFN
BQBSU BT XF EJE XJUI 4VN BOE 1SPEVDU
"EEJUJPO JT B DMBTTJD BQQFOEJOH PQFSBUJPO BT JT MJTU DPODBUF
OBUJPO 3FGFSSJOH UP NVMUJQMJDBUJPO BT B NBQQFOE PQFSBUJPO
NBZ BMTP TFFN JOUVJUJWF FOPVHI BT JU TUJMM GPMMPXT UIF CBTJD
QBUUFSO PG DPNCJOJOH UXP WBMVFT PG POF UZQF JOUP POF WBMVF
#VU GPS PUIFS EBUBUZQFT UIF NFBOJOH PG BQQFOE JT MFTT DMFBS
*O UIFTF DBTFT UIF NPOPJEBM PQFSBUJPO JT MFTT BCPVU DPNCJOJOH
UIF WBMVFT BOE NPSF BCPVU ƶOEJOH B TVNNBSZ WBMVF GPS UIF TFU
8F NFOUJPOFE BCPWF UIBU NPOPJET BSF JNQPSUBOU UP GPMEJOH
BOE DBUBNPSQIJTNT NPSF HFOFSBMMZ .BQQFOEJOH JT QFSIBQT
CFTU UIPVHIU PG OPU BT B XBZ PG DPNCJOJOH WBMVFT JO UIF XBZ UIBU
BEEJUJPO PS MJTU DPODBUFOBUJPO EPFT CVU BT B XBZ UP DPOEFOTF
BOZ TFU PG WBMVFT UP B TVNNBSZ WBMVF 8FƊMM TUBSU CZ MPPLJOH BU
UIF .POPJE JOTUBODFT GPS #PPM UP TFF XIBU XF NFBO
#PPMFBO WBMVFT IBWF UXP QPTTJCMF NPOPJET ƈ B NPOPJE PG
DPOKVODUJPO BOE POF PG EJTKVODUJPO "T XF EP XJUI OVNCFST
$)"15&3  .0/0*% 4&.*(3061 

XF VTF OFXUZQFT UP EJTUJOHVJTI UIF UXP JOTBODFT All BOE Any


BSF UIF OFXUZQFT GPS #PPMƊT NPOPJET

Prelude> import Data.Monoid

Prelude> All True <> All True


All {getAll = True}
Prelude> All True <> All False
All {getAll = False}

Prelude> Any True <> Any False


Any {getAny = True}
Prelude> Any False <> Any False
Any {getAny = False}

All SFQSFTFOUT CPPMFBO DPOKVODUJPO JU SFUVSOT B 5SVF JG BOE


POMZ JG BMM WBMVFT JU JT ƌBQQFOEJOHƍ BSF 5SVF Any JT UIF NPOPJE
PG CPPMFBO EJTKVODUJPO JU SFUVSOT B 5SVF JG BOZ WBMVF JT 5SVF
5IFSF JT TPNF TFOTF JO XIJDI JU NJHIU GFFM TUSBOHF UP UIJOL PG
UIJT BT B DPNCJOJOH PS NBQQFOEJOH PQFSBUJPO VOMFTT XF SFDBMM
UIBU NBQQFOEJOH JT MFTT BCPVU DPNCJOJOH BOE NPSF BCPVU
DPOEFOTJOH PS SFEVDJOH
5IF .BZCF UZQF BDUVBMMZ IBT NPSF UIBO UXP QPTTJCMF .POPJET
8FƊMM MPPL BU FBDI JO UVSO CVU UIF UXP UIBU IBWF BO PCWJPVT SFMB
UJPOTIJQ BSF 'JSTU BOE -BTU 5IFZ BSF MJLF CPPMFBO EJTKVODUJPO
CVU XJUI FYQMJDJU QSFGFSFODF GPS UIF MFǒNPTU PS SJHIUNPTU ƌTVD
DFTTƍ JO B TFSJFT PG .BZCF WBMVFT 8F IBWF UP DIPPTF CFDBVTF
$)"15&3  .0/0*% 4&.*(3061 

XJUI #PPM BMM ZPV LOPX JT 5SVF PS 'BMTF ƈ JU EPFTOƊU NBUUFS


XIFSF ZPVS 5SVF PS 'BMTF WBMVFT PDDVSSFE 8JUI .BZCF IPX
FWFS ZPV OFFE UP NBLF B EFDJTJPO BT UP XIJDI +VTU WBMVF ZPVƊMM
SFUVSO JG UIFSF BSF NVMUJQMF TVDDFTTFT 'JSTU BOE -BTU FODPEF
UIFTF EJƵFSFOU QPTTJCJMJUJFT
'JSTU SFUVSOT UIF ƌƶSTUƍ PS MFǒNPTU OPO/PUIJOH WBMVF

Prelude> First (Just 1) `mappend` First (Just 2)


First {getFirst = Just 1}

-BTU SFUVSOT UIF ƌMBTUƍ PS SJHIUNPTU OPO/PUIJOH WBMVF

Prelude> Last (Just 1) `mappend` Last (Just 2)


Last {getLast = Just 2}

#PUI XJMM TVDDFFE JO SFUVSOJOH TPNFUIJOH JO TQJUF PG /PUIJOH


WBMVFT BT MPOH BT UIFSFƊT BU MFBTU POF +VTU

Prelude> Last Nothing `mappend` Last (Just 2)


Last {getLast = Just 2}

Prelude> First Nothing `mappend` First (Just 2)


First {getFirst = Just 2}

/FJUIFS DBO GPS PCWJPVT SFBTPOT SFUVSO BOZUIJOH JG BMM WBM


VFT BSF /PUIJOH
$)"15&3  .0/0*% 4&.*(3061 

Prelude> First Nothing `mappend` First Nothing


First {getFirst = Nothing}

Prelude> Last Nothing `mappend` Last Nothing


Last {getLast = Nothing}

5P NBJOUBJO UIF VOJRVF QBJSJOH PG UZQF BOE UZQFDMBTT JO


TUBODF OFXUZQFT BSF VTFE GPS BMM PG UIPTF KVTU UIF TBNF BT XF
TBX XJUI 4VN BOE 1SPEVDU
-FUƊT MPPL OFYU BU UIF UIJSE WBSJFUZ PG .BZCF NPOPJE

 3FVTJOH BMHFCSBT CZ BTLJOH GPS


BMHFCSBT
8F BMMVEFE UP UIFSF CFJOH NPSF QPTTJCMF MonoidT GPS Maybe UIBO
KVTU First BOE Last 8F XJMM OPX XSJUF UIBU PUIFS Monoid JOTUBODF
8F XJMM OPX CF DPODFSOFE OPU XJUI DIPPTJOH POF WBMVF PVU PG
B TFU PG WBMVFT CVU PG DPNCJOJOH UIF Ԑ WBMVFT DPOUBJOFE XJUIJO
UIF Maybe a UZQF
'JSTU USZ UP OPUJDF B QBUUFSO

instance Monoid b => Monoid (a -> b)

instance (Monoid a, Monoid b) => Monoid (a, b)


instance (Monoid a, Monoid b, Monoid c) => Monoid (a, b, c)
$)"15&3  .0/0*% 4&.*(3061 

8IBU UIFTF .POPJET IBWF JO DPNNPO JT UIBU UIFZ BSF HJWJOH


ZPV B OFX .POPJE GPS B MBSHFS UZQF CZ SFVTJOH UIF .POPJE
JOTUBODFT PG UZQFT UIBU SFQSFTFOU DPNQPOFOUT PG UIF MBSHFS
UZQF
5IJT PCMJHBUJPO UP BTL GPS B .POPJE GPS BO FODBQTVMBUFE
UZQF TVDI BT UIF Ԑ JO Maybe a
FYJTUT FWFO XIFO OPU BMM QPTTJCMF
WBMVFT PG UIF MBSHFS UZQF DPOUBJO UIF WBMVF PG UIF UZQF BSHVNFOU
'PS FYBNQMF /PUIJOH EPFT OPU DPOUBJO UIF Ԑ XFƊSF USZJOH UP
HFU B .POPJE GPS CVU Just a EPFT TP OPU BMM QPTTJCMF .BZCF
WBMVFT DPOUBJO UIF Ԑ UZQF BSHVNFOU 'PS B .BZCF .POPJE UIBU
XJMM IBWF B NBQQFOE PQFSBUJPO GPS UIF Ԑ WBMVFT XF OFFE B
.POPJE GPS XIBUFWFS UZQF Ԑ JT .POPJET MJLF 'JSTU BOE -BTU
XSBQ UIF Maybe a CVU EP OPU SFRVJSF B .POPJE GPS UIF Ԑ WBMVF
JUTFMG CFDBVTF UIFZ EPOƊU NBQQFOE UIF Ԑ WBMVFT PS QSPWJEF B
NFNQUZ PG UIFN
*G ZPV EP IBWF B EBUBUZQF UIBU IBT B UZQF BSHVNFOU UIBU EPFT
OPU BQQFBS BOZXIFSF JO UIF UFSNT UIF UZQFDIFDLFS EPFT OPU
EFNBOE UIBU ZPV IBWF B .POPJE JOTUBODF GPS UIBU BSHVNFOU
'PS FYBNQMF
$)"15&3  .0/0*% 4&.*(3061 

data Booly a =
False'
| True'
deriving (Eq, Show)

-- conjunction; just cause.


instance Monoid (Booly a) where
mappend False' _ = False'
mappend _ False' = False'
mappend True' True' = True'

8F EJEOƊU OFFE B .POPJE DPOTUSBJOU GPS Ԑ CFDBVTF XFƊSF


OFWFS NBQQFOEJOH Ԑ WBMVFT XF DBOƊU OPOF FYJTU
BOE XFƊSF
OFWFS BTLJOH GPS B mempty PG UZQF Ԑ 5IJT JT UIF GVOEBNFOUBM
SFBTPO XF EPOƊU OFFE UIF DPOTUSBJOU CVU JU DBO IBQQFO UIBU XF
EPOƊU EP UIJT FWFO XIFO UIF UZQF EPFT PDDVS JO UIF EBUBUZQF

&YFSDJTF 0QUJPOBM .POPJE


8SJUF UIF Monoid JOTUBODF GPS PVS Maybe UZQF SFOBNFE UP Optional
$)"15&3  .0/0*% 4&.*(3061 

data Optional a =
Nada
| Only a
deriving (Eq, Show)

instance Monoid a => Monoid (Optional a) where


mempty = undefined
mappend = undefined

&YQFDUFE PVUQVU

Prelude> Only (Sum 1) `mappend` Only (Sum 1)


Only (Sum {getSum = 2})

Prelude> Only (Product 4) `mappend` Only (Product 2)


Only (Product {getProduct = 8})

Prelude> Only (Sum 1) `mappend` Nada


Only (Sum {getSum = 1})

Prelude> Only [1] `mappend` Nada


Only [1]

Prelude> Nada `mappend` Only (Sum 1)


Only (Sum {getSum = 1})
$)"15&3  .0/0*% 4&.*(3061 

"TTPDJBUJWJUZ
5IJT XJMM CF NPTUMZ SFWJFX CVU XF XBOU UP CF TQFDJƶD BCPVU
BTTPDJBUJWJUZ "TTPDJBUJWJUZ TJNQMZ TBZT UIBU ZPV DBO BTTPDJBUF
UIF BSHVNFOUT PG ZPVS PQFSBUJPO EJƵFSFOUMZ BOE UIF SFTVMU XJMM
CF UIF TBNF
-FUƊT SFWJFX FYBNQMFT PG TPNF PQFSBUJPOT UIBU DBO CF SFBT
TPDJBUFE

Prelude> (1 + 9001) + 9001


18003
Prelude> 1 + (9001 + 9001)
18003
Prelude> (7 * 8) * 3
168
Prelude> 7 * (8 * 3)
168

"OE TPNF UIBU DBOOPU IBWF UIF QBSFOUIFTFT SFBTTPDJBUFE


XJUIPVU DIBOHJOH UIF SFTVMU

Prelude> (1 - 10) - 100


-109
Prelude> 1 - (10 - 100)
91

5IJT JT OPU BT TUSPOH B QSPQFSUZ BT BO PQFSBUJPO UIBU DPN


NVUFT PS JT DPNNVUBUJWF $PNNVUBUJWF NFBOT ZPV DBO SFPSEFS
$)"15&3  .0/0*% 4&.*(3061 

UIF BSHVNFOUT BOE TUJMM HFU UIF TBNF SFTVMU "EEJUJPO BOE NVM
UJQMJDBUJPO BSF DPNNVUBUJWF CVU (++) GPS UIF MJTU UZQF JT POMZ
BTTPDJBUJWF
-FUƊT EFNPOTUSBUF UIJT CZ XSJUJOH B NJMEMZ FWJM WFSTJPO PG
BEEJUJPO UIBU ƷJQT UIF PSEFS PG JUT BSHVNFOUT

Prelude> let evilPlus = flip (+)


Prelude> 76 + 67
143
Prelude> 76 `evilPlus` 67
143

8F IBWF TPNF FWJEFODF CVU OPU QSPPG UIBU (+) DPNNVUFT


)PXFWFS XF DBOƊU EP UIF TBNF XJUI (++)

Prelude> let evilPlusPlus = flip (++)


Prelude> let oneList = [1..3]
Prelude> let otherList = [4..6]

Prelude> oneList ++ otherList


[1,2,3,4,5,6]

Prelude> oneList `evilPlusPlus` otherList


[4,5,6,1,2,3]

*O UIJT DBTF UIJT TFSWFT BT B QSPPG CZ DPVOUFSFYBNQMF UIBU


(++) EPFT OPU DPNNVUF *U EPFTOƊU NBUUFS JG JU DPNNVUFT GPS BMM
$)"15&3  .0/0*% 4&.*(3061 

PUIFS JOQVUT UIBU JU EPFTOƊU DPNNVUF GPS POF PG UIFN NFBOT


UIF MBX PG DPNNVUBUJWJUZ EPFT OPU IPME
$PNNVUBUJWJUZ JT B VTFGVM QSPQFSUZ BOE DBO CF IFMQGVM JO
DJSDVNTUBODFT XIFO ZPV NJHIU OFFE UP CF BCMF UP SFPSEFS
FWBMVBUJPO PG ZPVS EBUB GPS FƸDJFODZ QVSQPTFT XJUIPVU OFFE
JOH UP XPSSZ BCPVU UIF SFTVMU DIBOHJOH %JTUSJCVUFE TZTUFNT
VTF DPNNVUBUJWF NPOPJET JO EFTJHOJOH BOE UIJOLJOH BCPVU
DPOTUSBJOUT XIJDI BSF NPOPJET UIBU HVBSBOUFF UIFJS PQFSBUJPO
DPNNVUFT
#VU GPS PVS QVSQPTFT .POPJE BCJEFT CZ UIF MBX PG BTTP
DJBUJWJUZ CVU OPU UIF MBX PG DPNNVUBUJWJUZ FWFO UIPVHI TPNF
NPOPJEBM PQFSBUJPOT BEEJUJPO BOE NVMUJQMJDBUJPO
BSF DPN
NVUBUJWF

*EFOUJUZ
"O JEFOUJUZ JT B WBMVF XJUI B TQFDJBM SFMBUJPOTIJQ XJUI BO PQFS
BUJPO JU UVSOT UIF PQFSBUJPO JOUP UIF JEFOUJUZ GVODUJPO 5IFSF
BSF OP JEFOUJUJFT XJUIPVU PQFSBUJPOT 5IF WFSZ DPODFQU JT EF
ƶOFE JO UFSNT PG JUT SFMBUJPOTIJQ XJUI B HJWFO PQFSBUJPO *G
ZPVƊWF EPOF HSBEF TDIPPM BSJUINFUJD ZPVƊWF BMSFBEZ TFFO TPNF
JEFOUJUJFT

Prelude> 1 + 0
1
Prelude> 521 + 0
521
$)"15&3  .0/0*% 4&.*(3061 

Prelude> 1 * 1
1
Prelude> 521 * 1
521

;FSP JT UIF JEFOUJUZ WBMVF GPS BEEJUJPO XIJMF  JT UIF JEFOUJUZ


WBMVF GPS NVMUJQMJDBUJPO "T XF TBJE JU EPFTOƊU NBLF TFOTF UP
UBML BCPVU [FSP BOE POF BT ƌJEFOUJUZ WBMVFTƍ PVUTJEF UIF DPOUFYU
PG UIPTF PQFSBUJPOT 5IBU JT [FSP JT EFƶOJUFMZ OPU UIF JEFOUJUZ
WBMVF GPS PUIFS PQFSBUJPOT 8F DBO DIFDL UIJT QSPQFSUZ XJUI B
TJNQMF FRVBMJUZ UFTU BT XFMM

Prelude> let myList = [1..424242]


Prelude> map (+0) myList == myList
True

Prelude> map (*1) myList == myList


True

5IJT JT UIF PUIFS MBX GPS .POPJE UIF CJOBSZ PQFSBUJPO NVTU
CF BTTPDJBUJWF BOE JU NVTU IBWF B TFOTJCMF JEFOUJUZ WBMVF

5IF QSPCMFN PG PSQIBO JOTUBODFT


8FƊWF TBJE CPUI JO UIJT DIBQUFS BOE JO UIF FBSMJFS DIBQUFS EF
WPUFE UP 5ZQFDMBTTFT UIBU UZQFDMBTTFT IBWF VOJRVF QBJSJOHT PG
UIF DMBTT BOE UIF JOTUBODF GPS B QBSUJDVMBS UZQF
$)"15&3  .0/0*% 4&.*(3061 

8F EP TPNFUJNFT FOE VQ XJUI NVMUJQMF JOTUBODFT GPS B


TJOHMF UZQF XIFO PSQIBO JOTUBODFT BSF XSJUUFO #VU XSJUJOH
PSQIBO JOTUBODFT TIPVME CF BWPJEFE BU BMM DPTUT %P OPU CF MB[Z
BCPVU UIJT *G ZPV HFU BO PSQIBO JOTUBODF XBSOJOH GSPN ()$
ƶY JU
"O PSQIBO JOTUBODF JT XIFO BO JOTUBODF JT EFƶOFE GPS B
EBUBUZQF BOE UZQFDMBTT CVU OPU JO UIF TBNF NPEVMF BT FJUIFS
UIF EFDMBSBUJPO PG UIF UZQFDMBTT PS UIF EBUBUZQF *G ZPV EPOƊU
ƌPXOƍ UIF UZQFDMBTT PS UIF EBUBUZQF OFXUZQF JU
*G ZPV XBOU BO PSQIBO JOTUBODF TP UIBU ZPV DBO IBWF NVMUJ
QMF JOTUBODFT GPS UIF TBNF UZQF ZPV TUJMM XBOU UP VTF OFXUZQF
8F TBX UIJT FBSMJFS XJUI 4VN BOE 1SPEVDU XIJDI MFU VT IBWF
UXP EJƵFSFOU .POPJE JOTUBODFT GPS OVNCFST XJUIPVU SFTPSUJOH
UP PSQIBOT PS NFTTJOH VQ UZQFDMBTT JOTUBODF VOJRVFOFTT
-FUƊT TFF BO FYBNQMF PG BO PSQIBO JOTUBODF BOE IPX UP ƶY JU
'JSTU NBLF B QSPKFDU EJSFDUPSZ BOE DIBOHF JOUP UIBU EJSFDUPSZ

$ mkdir orphan-instance && cd orphan-instance

5IFO XFƊSF HPJOH UP NBLF B DPVQMF PG ƶMFT POF NPEVMF JO


FBDI

module Listy where

newtype Listy a =
Listy [a]
deriving (Eq, Show)
$)"15&3  .0/0*% 4&.*(3061 

module ListyInstances where

import Data.Monoid
import Listy

instance Monoid (Listy a) where


mempty = Listy []
mappend (Listy l) (Listy l') = Listy $ mappend l l'

4P PVS EJSFDUPSZ XJMM MPPL MJLF

$ tree
.
├── Listy.hs
└── ListyInstances.hs

5IFO UP CVJME -JTUZ*OTUBODFT TVDI UIBU JU DBO TFF Listy XF


NVTU VTF UIF -I ƷBH UP ƌJODMVEFƍ UIF DVSSFOU EJSFDUPSZ BOE
NBLF NPEVMFT XJUIJO JU EJTDPWFSBCMF 5IF . BǒFS UIF I JT IPX
XF TBZ ƌUIJT EJSFDUPSZƍ JO 6OJYBMJLFT *G ZPV TVDDFFE ZPV
TIPVME TFF TPNFUIJOH MJLF UIF GPMMPXJOH

$ ghc -I. --make ListyInstances.hs


[2 of 2] Compiling ListyInstances

/PUF UIBU UIF POMZ PVUQVU XJMM CF BO PCKFDU ƶMF UIF SFTVMU PG
DPNQJMJOH B NPEVMF UIBU DBO CF SFVTFE BT B MJCSBSZ CZ )BTLFMM
$)"15&3  .0/0*% 4&.*(3061 

DPEF CFDBVTF XF EJEOƊU EFƶOF B main TVJUBCMF GPS QSPEVDJOH BO


FYFDVUBCMF 8FƊSF POMZ VTJOH UIJT BQQSPBDI UP CVJME UIJT TP UIBU
XF DBO BWPJE UIF IBTTMF PG cabal initƊJOH B QSPKFDU 'PS BOZUIJOH
NPSF DPNQMJDBUFE PS MPOHMJWFE UIBO UIJT VTF B EFQFOEFODZ
BOE CVJME NBOBHFNFOU UPPM MJLF $BCBM
/PX UP QSPWJEF POF FYBNQMF PG XIZ PSQIBO JOTUBODFT BSF
QSPCMFNBUJD *G XF DPQZ PVS .POPJE JOTUBODF GSPN -JTUZ*O
TUBODFT JOUP -JTUZ UIFO SFCVJME -JTUZ*OTUBODFT XFƊMM HFU UIF
GPMMPXJOH FSSPS

$ ghc -I. --make ListyInstances.hs


[1 of 2] Compiling Listy
[2 of 2] Compiling ListyInstances

Listy.hs:7:10:
Duplicate instance declarations:
instance Monoid (Listy a) -- Defined at Listy.hs:7:10
instance Monoid (Listy a) -- Defined at ListyInstances.hs:5:10

5IFTF DPOƷJDUJOH JOTUBODF EFDMBSBUJPOT DPVME IBQQFO UP


BOZCPEZ XIP VTFT UIF QSFWJPVT WFSTJPO PG PVS DPEF "OE
UIBUƊT B QSPCMFN
0SQIBO JOTUBODFT BSF TUJMM B QSPCMFN FWFO JG EVQMJDBUF JO
TUBODFT BSFOƊU CPUI JNQPSUFE JOUP B NPEVMF CFDBVTF JU NFBOT
ZPVS UZQFDMBTT NFUIPET XJMM TUBSU CFIBWJOH EJƵFSFOUMZ EFQFOE
JOH PO XIBU NPEVMFT BSF JNQPSUFE XIJDI CSFBLT UIF GVOEB
NFOUBM BTTVNQUJPOT BOE OJDFUJFT PG UZQFDMBTTFT
$)"15&3  .0/0*% 4&.*(3061 

5IFSF BSF B GFX TPMVUJPOT GPS BEESFTTJOH PSQIBO JOTUBODFT

 :PV EFƶOFE UIF UZQF CVU OPU UIF UZQFDMBTT 1VU UIF JO
TUBODF JO UIF TBNF NPEVMF BT UIF UZQF TP UIBU UIF UZQF
DBOOPU CF JNQPSUFE XJUIPVU JUT JOTUBODFT

 :PV EFƶOFE UIF UZQFDMBTT CVU OPU UIF UZQF 1VU UIF JO
TUBODF JO UIF TBNF NPEVMF BT UIF UZQFDMBTT EFƶOJUJPO
TP UIBU UIF UZQFDMBTT DBOOPU CF JNQPSUFE XJUIPVU JUT JO
TUBODFT

 /FJUIFS UIF UZQF OPS UIF UZQFDMBTT BSF ZPVST %FƶOF ZPVS
PXO OFXUZQF XSBQQJOH UIF PSJHJOBM UZQF BOE OPX ZPVƊWF
HPU B UZQF UIBU ƌCFMPOHTƍ UP ZPV GPS XIJDI ZPV DBO SJHIUMZ
EFƶOF UZQFDMBTT JOTUBODFT 5IFSF BSF NFBOT PG NBLJOH
UIJT MFTT BOOPZJOH XIJDI XFƊMM EJTDVTT MBUFS

5IFTF SFTUSJDUJPOT NVTU CF NBJOUBJOFE JO PSEFS GPS VT UP


SFBQ UIF GVMM CFOFƶU PG UZQFDMBTTFT BMPOH XJUI UIF OJDF SFBTPO
JOH QSPQFSUJFT UIBU BSF BTTPDJBUFE XJUI UIFN " UZQF NVTU IBWF
B VOJRVF TJOHVMBS
JNQMFNFOUBUJPO PG B UZQFDMBTT JO TDPQF
BOE BWPJEJOH PSQIBO JOTUBODFT JT IPX XF QSFWFOU DPOƷJDU
JOH JOTUBODFT #F BXBSF IPXFWFS UIBU BWPJEBODF PG PSQIBO
JOTUBODFT JT NPSF TUSJDUMZ BEIFSFE UP BNPOH MJCSBSZ BVUIPST
SBUIFS UIBO BQQMJDBUJPO EFWFMPQFST BMUIPVHI JUƊT OP MFTT JN
QPSUBOU JO BQQMJDBUJPOT
$)"15&3  .0/0*% 4&.*(3061 

 .BEOFTT
:PV NBZ IBWF TFFO NBE MJCT CFGPSF 5IF JEFB JT UP UBLF B UFN
QMBUF PG QISBTFT ƶMM UIFN JO XJUI CMJOEMZ TFMFDUFE DBUFHPSJFT
PG XPSET BOE TFF JG TBZJOH UIF ƶOBM WFSTJPO JT BNVTJOH
6TJOH B MJHIUMZ FEJUFE FYBNQMF GSPN UIF 8JLJQFEJB BSUJDMF
PO .BE -JCT

"___________! he said ______ as he


exclamation adverb
jumped into his car ____ and drove
noun
off with his _________ wife."
adjective

8F DBO NBLF UIJT JOUP B GVODUJPO MJLF UIF GPMMPXJOH

import Data.Monoid

type Verb = String


type Adjective = String
type Adverb = String
type Noun = String
type Exclamation = String

https://en.wikipedia.org/wiki/Mad_Libs
$)"15&3  .0/0*% 4&.*(3061 

madlibbin' :: Exclamation
-> Adverb
-> Noun
-> Adjective
-> String
madlibbin' e adv noun adj =
e <> "! he said " <>
adv <> " as he jumped into his car " <>
noun <> " and drove off with his " <>
adj <> " wife."

/PX ZPVƊSF HPJOH UP SFGBDUPS UIJT DPEF B CJU 3FXSJUF JU VTJOH


mconcat

madlibbinBetter' :: Exclamation
-> Adverb
-> Noun
-> Adjective
-> String
madlibbinBetter' e adv noun adj = undefined

 #FUUFS MJWJOH UISPVHI 2VJDL$IFDL


1SPWJOH MBXT DBO CF UFEJPVT FTQFDJBMMZ JG UIF DPEF XFƊSF DIFDL
JOH JT JO UIF NJEEMF PG DIBOHJOH GSFRVFOUMZ "DDPSEJOHMZ IBW
JOH B DIFBQ XBZ UP HFU B TFOTF PG XIFUIFS PS OPU UIF MBXT BSF
$)"15&3  .0/0*% 4&.*(3061 

MJLFMZ UP CF PCFZFE CZ BO JOTUBODF JT QSFUUZ VTFGVM 2VJDL$IFDL


IBQQFOT UP CF BO FYDFMMFOU XBZ UP BDDPNQMJTI UIJT

7BMJEBUJOH BTTPDJBUJWJUZ XJUI 2VJDL$IFDL


:PV DBO DIFDL UIF BTTPDJBUJWJUZ PG TPNF TJNQMF BSJUIFNFUJD
FYQSFTTJPOT CZ BTTFSUJOH FRVBMJUZ CFUXFFO UXP WFSTJPOT XJUI
EJƵFSFOU QBSFOUIFTJ[BUJPO BOE DIFDLJOH UIFN JO UIF 3&1-

-- we're saying these are the same because


-- (+) and (*) are associative

1 + (2 + 3) == (1 + 2) + 3

4 * (5 * 6) == (4 * 5) * 6

5IJT EPFTOƊU UFMM VT UIBU BTTPDJBUJWJUZ IPMET GPS BOZ JOQVUT UP


(+) BOE (*) UIPVHI BOE UIBU JT XIBU XF XBOU UP UFTU 0VS PME
GSJFOE GSPN UIF MBNCEB DBMDVMVT ƈ BCTUSBDUJPO ƈ TVƸDFT GPS
UIJT

\ a b c -> a + (b + c) == (a + b) + c

\ a b c -> a * (b * c) == (a * b) * c

#VU PVS BSHVNFOUT BSFOƊU UIF POMZ UIJOH XF DBO BCTUSBDU


8IBU JG XF XBOU UP UBML BCPVU UIF BCTUSBDU QSPQFSUZ PG BTTPDJB
UJWJUZ GPS TPNF HJWFO GVODUJPO ԕ
$)"15&3  .0/0*% 4&.*(3061 

\ f a b c ->
f a (f b c) == f (f a b) c
-- or infix

\ (<>) a b c ->
a <> (b <> c) == (a <> b) <> c

4VSQSJTF :PV DBO CJOE JOƶY OBNFT GPS GVODUJPO BSHVNFOUT

asc :: Eq a => (a -> a -> a) -> a -> a -> a -> Bool


asc (<>) a b c =
a <> (b <> c) == (a <> b) <> c

/PX IPX EP XF UVSO UIJT GVODUJPO JOUP TPNFUIJOH XF DBO


RVJDLDIFDL 5IF RVJDLFTU BOE FBTJFTU XBZ XPVME QSPCBCMZ
MPPL TPNFUIJOH MJLF UIF GPMMPXJOH

import Data.Monoid
import Test.QuickCheck

monoidAssoc :: (Eq m, Monoid m) => m -> m -> m -> Bool


monoidAssoc a b c = (a <> (b <> c)) == ((a <> b) <> c)

8F IBWF UP EFDMBSF UIF UZQFT GPS UIF GVODUJPO JO PSEFS UP


SVO UIF UFTUT TP UIBU 2VJDL$IFDL LOPXT XIBU UZQFT PG EBUB UP
HFOFSBUF
8F DBO OPX VTF UIJT UP DIFDL BTTPDJBUJWJUZ PG GVODUJPOT
$)"15&3  .0/0*% 4&.*(3061 

-- for brevity
Prelude> type S = String
Prelude> type B = Bool

Prelude> quickCheck (monoidAssoc :: S -> S -> S -> B)


+++ OK, passed 100 tests.

5IF quickCheck GVODUJPO VTFT UIF Arbitrary UZQFDMBTT UP QSP


WJEF UIF SBOEPNMZ HFOFSBUFE JOQVUT GPS UFTUJOH UIF GVODUJPO
"MUIPVHI JUƊT DPNNPO UP EP TP XF NBZ OPU XBOU UP SFMZ PO
BO "SCJUSBSZ JOTUBODF FYJTUJOH GPS UIF UZQF PG PVS JOQVUT 8F
NBZ OPU XBOU UP EP UIJT GPS POF PG B GFX SFBTPOT *U NBZ CF
UIBU XF OFFE B HFOFSBUPS GPS B UZQF UIBU EPFTOƊU CFMPOH UP VT
TP XFƊE SBUIFS OPU NBLF BO PSQIBO JOTUBODF 0S JU DPVME CF
B UZQF UIBU BMSFBEZ IBT BO BSCJUSBSZ JOTUBODF CVU XF XBOU UP
SVO UFTUT XJUI B EJƵFSFOU SBOEPN EJTUSJCVUJPO PG WBMVFT PS UP
NBLF TVSF XF DIFDL DFSUBJO TQFDJBM FEHF DBTFT JO BEEJUJPO UP
UIF SBOEPN WBMVFT
:PV XBOU UP CF DBSFGVM UP BTTFSU UZQFT TP UIBU 2VJDL$IFDL
LOPXT XIJDI "SCJUSBSZ JOTUBODF UP HFU SBOEPN WBMVFT GPS UFTU
JOH GSPN :PV DBO VTF verboseCheck UP TFF XIBU WBMVFT XFSF
UFTUFE *G ZPV USZ SVOOJOH UIF DIFDL WFSCPTFMZ BOE XJUIPVU
BTTFSUJOH B UZQF GPS UIF BSHVNFOUT

Prelude> verboseCheck monoidAssoc


Passed:
$)"15&3  .0/0*% 4&.*(3061 

()
()
()

(repeated 100 times)

5IJT JT ()$JƊT UZQFEFGBVMUJOH CJUJOH ZPV BT XF TBX CBDL JO


UIF 5FTUJOH DIBQUFS ()$J IBT TMJHIUMZ NPSF BHHSFTTJWF UZQF
EFGBVMUJOH XIJDI DBO CF IBOEZ JO BO JOUFSBDUJWF TFTTJPO XIFO
ZPV KVTU XBOU UP ƶSF PƵ TPNF DPEF BOE IBWF ZPVS 3&1- QJDL
B XJOOFS GPS UIF UZQFDMBTTFT JU EPFTOƊU LOPX IPX UP EJTQBUDI
$PNQJMFE JO B TPVSDF ƶMF ()$ XPVMEƊWF TRVBXLFE BCPVU BO
BNCJHVPVT UZQF

2VJDLDIFDLJOH MFǒ BOE SJHIU JEFOUJUZ


'PMMPXJOH PO GSPN XIBU XF EJE XJUI BTTPDJBUJWJUZ MFǒ BOE
SJHIU JEFOUJUZ UVSO PVU UP CF FWFO TJNQMFS UP UFTU

monoidLeftIdentity :: (Eq m, Monoid m) => m -> Bool


monoidLeftIdentity a = (mempty <> a) == a

monoidRightIdentity :: (Eq m, Monoid m) => m -> Bool


monoidRightIdentity a = (a <> mempty) == a

5IFO SVOOJOH UIFTF QSPQFSUJFT BHBJOTU B .POPJE


$)"15&3  .0/0*% 4&.*(3061 

Prelude> quickCheck (monoidLeftIdentity :: String -> Bool)


+++ OK, passed 100 tests.

Prelude> quickCheck (monoidRightIdentity :: String -> Bool)


+++ OK, passed 100 tests.

5FTUJOH 2VJDL$IFDLƊT QBUJFODF


-FU VT TFF BO FYBNQMF PG 2VJDL$IFDL DBUDIJOH VT PVU GPS IBW
JOH BO JOWBMJE .POPJE )FSF XFƊSF HPJOH UP EFNPOTUSBUF XIZ B
#PPM .POPJE DBOƊU IBWF 'BMTF BT UIF JEFOUJUZ BMXBZT SFUVSOJOH
UIF WBMVF 'BMTF BOE TUJMM CF B WBMJE .POPJE

-- associative, left identity, and right identity


-- properties have been elided. Add them to your copy of this.

import Control.Monad
import Data.Monoid
import Test.QuickCheck

data Bull =
Fools
| Twoo
deriving (Eq, Show)
$)"15&3  .0/0*% 4&.*(3061 

instance Arbitrary Bull where


arbitrary =
frequency [ (1, return Fools)
, (1, return Twoo) ]

instance Monoid Bull where


mempty = Fools
mappend _ _ = Fools

type BullMappend = Bull -> Bull -> Bull -> Bool

main :: IO ()
main = do
quickCheck (monoidAssoc :: BullMappend)
quickCheck (monoidLeftIdentity :: Bull -> Bool)
quickCheck (monoidRightIdentity :: Bull -> Bool)

*G ZPV MPBE UIJT VQ JO ()$J BOE SVO main ZPVƊMM HFU UIF
GPMMPXJOH PVUQVU

Prelude> main
+++ OK, passed 100 tests.
*** Failed! Falsifiable (after 1 test):
Twoo
*** Failed! Falsifiable (after 1 test):
Twoo
$)"15&3  .0/0*% 4&.*(3061 

4P UIJT OPUBDUVBMMZB.POPJE GPS #PPM UVSOT PVU UP QBTT


BTTPDJBUJWJUZ CVU GBJM PO UIF SJHIU BOE MFǒ JEFOUJUZ DIFDLT 5P
TFF XIZ MFUT MJOF VQ UIF MBXT BHBJOTU XIBU PVS NFNQUZ BOE
NBQQFOE BSF

-- how the instance is defined


mempty = Fools
mappend _ _ = Fools

-- identity laws
mappend mempty x = x
mappend x mempty = x

-- Does it obey the laws?

-- because of how mappend is defined


mappend mempty x = Fools
mappend x mempty = Fools

-- Fools is not x, so it fails the identity laws.

*UƊT ƶOF JG ZPVS JEFOUJUZ WBMVF JT Fools CVU JG ZPVS NBQQFOE


BMXBZT SFUVSOT UIF JEFOUJUZ UIFO JUƊT OPU BO JEFOUJUZ *UƊT OPU
FWFO CFIBWJOH MJLF B [FSP BT ZPVƊSF OPU FWFO DIFDLJOH JG FJUIFS
BSHVNFOU JT Fools CFGPSF SFUVSOJOH Fools *UƊT BO FWJM CMBDLIPMF
UIBU KVTU TQJUT PVU POF WBMVF XIJDI JT TFOTFMFTT 'PS BO FYBNQMF
$)"15&3  .0/0*% 4&.*(3061 

PG XIBU JT NFBOU CZ [FSP DPOTJEFS NVMUJQMJDBUJPO XIJDI IBT


BO JEFOUJUZ BOE B [FSP

-- Thus why the mempty for Sum is 0


0 + x == x
x + 0 == x

-- Thus why the mempty for Product is 1


1 * x == x
x * 1 == x

-- Thus why the mempty for Product is *not* 0


0 * x == 0
x * 0 == 0

6TJOH 2VJDL$IFDL DBO CF B HSFBU XBZ UP DIFBQMZ BOE FBTJMZ


TBOJUZ DIFDL UIF WBMJEJUZ PG ZPVS JOTUBODFT BHBJOTU UIFJS MBXT
:PVƊMM TFF NPSF PG UIJT

&YFSDJTF .BZCF "OPUIFS .POPJE


8SJUF B Monoid JOTUBODF GPS Maybe UZQF XIJDI EPFTOƊU SFRVJSF
B Monoid GPS UIF DPOUFOUT 3FVTF UIF Monoid MBX 2VJDL$IFDL
QSPQFSUJFT BOE VTF UIFN UP WBMJEBUF UIF JOTUBODF
$)"15&3  .0/0*% 4&.*(3061 

-- Don't forget to write an Arbitrary


-- instance for First'. We won't always
-- stub that out explicitly for you.

newtype First' a =
First' { getFirst' :: Optional a }
deriving (Eq, Show)

instance Monoid (First' a) where


mempty = undefined
mappend = undefined

firstMappend :: First' a
-> First' a
-> First' a
firstMappend = mappend
$)"15&3  .0/0*% 4&.*(3061 

type FirstMappend =
First' String
-> First' String
-> First' String
-> Bool

type FstId =
First' String -> Bool

main :: IO ()
main = do
quickCheck (monoidAssoc :: FirstMappend)
quickCheck (monoidLeftIdentity :: FstId)
quickCheck (monoidRightIdentity :: FstId)

0VS FYQFDUFE PVUQVU EFNPOTUSBUFT B EJƵFSFOU .POPJE GPS


0QUJPOBM.BZCF XIJDI JT HFUUJOH UIF ƶSTU TVDDFTT BOE IPMEJOH
POUP JU XIFSF BOZ FYJTU 5IJT DPVME CF TFFO XJUI B CJU PG IBOE
XBWJOH BT CFJOH MJLF B EJTKVODUJWF PS ƌPSƍPSJFOUFE .POPJE
JOTUBODF

Prelude> First' (Only 1) `mappend` First' Nada


First' {getFirst' = Only 1}
Prelude> First' Nada `mappend` First' Nada
First' {getFirst' = Nada}
Prelude> First' Nada `mappend` First' (Only 2)
$)"15&3  .0/0*% 4&.*(3061 

First' {getFirst' = Only 2}


Prelude> First' (Only 1) `mappend` First' (Only 2)
First' {getFirst' = Only 1}

 4FNJHSPVQ
.BUIFNBUJDJBOT QMBZ XJUI BMHFCSBT MJLF UIBU DSFFQZ LJE ZPV
LOFX JO HSBEF TDIPPM XIP XPVME QVMM MFHT PƵ PG JOTFDUT 4PNF
UJNFT UIFZ HMVF MFHT POUP JOTFDUT UPP CVU JO UIF DBTF XIFSF
XFƊSF HPJOH GSPN .POPJE UP 4FNJHSPVQ XFƊSF QVMMJOH B MFH
PƵ *O UIJT DBTF UIF MFH JT PVS JEFOUJUZ 5P HFU GSPN B NPOPJE
UP B TFNJHSPVQ XF TJNQMZ OP MPOHFS GVSOJTI OPS SFRVJSF BO
JEFOUJUZ 5IF DPSF PQFSBUJPO SFNBJOT CJOBSZ BOE BTTPDJBUJWF
8JUI UIJT PVS EFƶOJUJPO PG Semigroup JT

class Semigroup a where


(<>) :: a -> a -> a

"OE XFƊSF MFǒ XJUI POF MBX

(a <> b) <> c = a <> (b <> c)

4FNJHSPVQ TUJMM QSPWJEFT B CJOBSZ BTTPDJBUJWF PQFSBUJPO POF


UIBU UZQJDBMMZ KPJOT UXP UIJOHT UPHFUIFS BT JO DPODBUFOBUJPO PS
TVNNBUJPO
CVU EPFTOƊU IBWF BO JEFOUJUZ WBMVF *O UIBU TFOTF
JUƊT B XFBLFS BMHFCSB
$)"15&3  .0/0*% 4&.*(3061 

/PU ZFU QBSU PG CBTF "T PG UIF XSJUJOH PG UIJT CPPL UIF Semigroup
UZQFDMBTT JTOƊU ZFU QBSU PG CBTF 8JUI UIF SFMFBTF PG ()$ 
TFNJHSPVQ TIPVME CF QBSU PG CBTF BOE B TVQFSDMBTT PG .POPJE
5P GPMMPX BMPOH XJUI UIF FYBNQMFT ZPVƊMM XBOU UP JOTUBMM UIF
TFNJHSPVQT MJCSBSZ BOE VTF JU GSPN B cabal repl
*G ZPV EP JOTUBMM 4FNJHSPVQT BOE JNQPSU UIF NPEVMFT LFFQ
JO NJOE UIBU JU EFƶOFT JUT PXO NPSF HFOFSBM WFSTJPO PG (<>)
XIJDI POMZ SFRVJSFT B 4FNJHSPVQ DPOTUSBJOU SBUIFS UIBO B
.POPJE DPOTUSBJOU *G ZPV EPOƊU LOPX XIBU UP EP DMPTF ZPVS
3&1- BOE SFPQFO JU "ǒFS EPJOH TP UIFO JNQPSU POMZ UIF
TFNJHSPVQT NPEVMF BOE OPU %BUB.POPJE GSPN CBTF *G ZPV
NVTU JNQPSU %BUB.POPJE IJEF UIF DPOƷJDUJOH (<>) JO ZPVS
JNQPSU EFDMBSBUJPO

/PO&NQUZ B VTFGVM EBUBUZQF


0OF SFBMMZ VTFGVM EBUBUZQF UIBU DBOƊU IBWF B Monoid JOTUBODF CVU
EPFT IBWF B Semigroup JOTUBODF JT UIF NonEmpty MJTU UZQF *U JT B
MJTU EBUBUZQF UIBU DBO OFWFS CF BO FNQUZ MJTU

data NonEmpty a = a :| [a]


deriving (Eq, Ord, Show)

-- some instances from the real library elided



http://hackage.haskell.org/package/semigroups
$)"15&3  .0/0*% 4&.*(3061 

)FSF :| JT BO JOƶY EBUB DPOTUSVDUPS UIBU UBLFT UXP UZQF

BSHVNFOUT *UƊT B QSPEVDU PG a BOE [a] *U HVBSBOUFFT UIBU XF


BMXBZT IBWF BU MFBTU POF WBMVF PG UZQF a XIJDI [a] EPFT OPU
HVBSBOUFF BT BOZ MJTU NJHIU CF FNQUZ
/PUF UIBU BMUIPVHI :| JT OPU BMQIBOVNFSJD BT NPTU PG UIF
PUIFS EBUB DPOTUSVDUPST ZPVƊSF VTFE UP TFFJOH BSF JU JT KVTU B
OBNF GPS BO JOƶY EBUB DPOTUSVDUPS %BUB DPOTUSVDUPST XJUI
POMZ OPOBMQIBOVNFSJD TZNCPMT BOE UIBU CFHJO XJUI B DPMPO
BSF JOƶY CZ EFGBVMU UIPTF XJUI BMQIBOVNFSJD OBNFT BSF QSFƶY
CZ EFGBVMU

-- Prefix, works.
data P =
Prefix Int String

-- Infix, works.
data Q =
Int :!!: String

4JODF UIBU EBUB DPOTUSVDUPS JT TZNCPMJD SBUIFS UIBO BMQIBOV


NFSJD JU DBOƊU CF VTFE BT B QSFƶY

data R =
:!!: Int String

6TJOH JU BT B QSFƶY XJMM DBVTF B TZOUBY FSSPS


$)"15&3  .0/0*% 4&.*(3061 

parse error on input ‘:!!:’


Failed, modules loaded: none.

0O UIF PUIFS IBOE BO BMQIBOVNFSJD EBUB DPOTUSVDUPS DBOƊU


CF VTFE BT BO JOƶY

data S =
Int Prefix String

*U XJMM DBVTF BOPUIFS FSSPS

Not in scope: type constructor or class ‘Prefix’


A data constructor of that name is in scope;
did you mean DataKinds?
Failed, modules loaded: none.

-FUƊT SFUVSO UP UIF NBJO QPJOU XIJDI JT NonEmpty #FDBVTF


NonEmpty JT B QSPEVDU PG UXP BSHVNFOUT XF DPVMEƊWF BMTP XSJUUFO
JU BT

newtype NonEmpty a =
NonEmpty (a, [a])
deriving (Eq, Ord, Show)

8F DBOƊU XSJUF B .POPJE GPS NonEmpty CFDBVTF JU IBT OP JEFO


UJUZ WBMVF CZ EFTJHO 5IFSF JT OP FNQUZ MJTU UP TFSWF BT BO
JEFOUJUZ GPS BOZ PQFSBUJPO PWFS B /PO&NQUZ MJTU ZFU UIFSF
JT TUJMM B CJOBSZ BTTPDJBUJWF PQFSBUJPO UXP /PO&NQUZ MJTUT
$)"15&3  .0/0*% 4&.*(3061 

DBO TUJMM CF DPODBUFOBUFE " UZQF XJUI B DBOPOJDBM CJOBSZ BT


TPDJBUJWF PQFSBUJPO CVU OP JEFOUJUZ WBMVF JT B OBUVSBM ƶU GPS
4FNJHSPVQ )FSF JT B CSJFG FYBNQMF PG VTJOH /PO&NQUZ GSPN
UIF TFNJHSPVQT MJCSBSZ XJUI UIF TFNJHSPVQ ƌNBQQFOEƍ

-- you need to have `semigroups` installed


Prelude> import Data.List.NonEmpty as N
Prelude N> import Data.Semigroup as S
Prelude N S> 1 :| [2, 3]
1 :| [2,3]
Prelude N S> :t 1 :| [2, 3]
1 :| [2, 3] :: Num a => NonEmpty a
Prelude N S> :t (<>)
(<>) :: Semigroup a => a -> a -> a

Prelude N S> let xs = 1 :| [2, 3]


Prelude N S> let ys = 4 :| [5, 6]
Prelude N S> xs <> ys
1 :| [2,3,4,5,6]
Prelude N S> N.head xs
1
Prelude N S> N.length (xs <> ys)
6

#FZPOE UIJT ZPV VTF /PO&NQUZ KVTU MJLF ZPV XPVME B MJTU
CVU XIBU ZPVƊWF HBJOFE JT CFJOH FYQMJDJU UIBU IBWJOH [FSP WBMVFT
$)"15&3  .0/0*% 4&.*(3061 

JT OPU WBMJE GPS ZPVS VTFDBTF 5IF EBUBUZQF IFMQT ZPV FOGPSDF
UIJT DPOTUSBJOU CZ OPU MFUUJOH ZPV DPOTUSVDU B /PO&NQUZ VOMFTT
ZPV IBWF BU MFBTU POF WBMVF

4USFOHUI DBO CF XFBLOFTT


8IFO )BTLFMMFST UBML BCPVU UIF TUSFOHUI PG BO BMHFCSB UIFZ
VTVBMMZ NFBO UIF OVNCFS PG PQFSBUJPOT JU QSPWJEFT XIJDI JO
UVSO FYQBOET XIBU ZPV DBO EP XJUI BOZ HJWFO JOTUBODF PG UIBU
BMHFCSB XJUIPVU OFFEJOH UP LOPX TQFDJƶDBMMZ XIBU UZQF ZPV
BSF XPSLJOH XJUI
5IF SFBTPO XF DBOOPU BOE EP OPU XBOU UP TJNQMZ NBLF BMM
PG PVS BMHFCSBT BT CJH BT QPTTJCMF JT UIBU UIFSF BSF EBUBUZQFT
XIJDI BSF WFSZ VTFGVM SFQSFTFOUBUJPOBMMZ CVU XIJDI EP OPU
IBWF UIF BCJMJUZ UP TBUJTGZ FWFSZUIJOH JO B MBSHFS BMHFCSB UIBU
DPVME XPSL ƶOF JG ZPV SFNPWFE BO PQFSBUJPO PS MBX 5IJT
CFDPNFT B TFSJPVT QSPCMFN JG /PO&NQUZ JT UIF SJHIU EBUBUZQF
GPS TPNFUIJOH JO UIF EPNBJO ZPVƊSF SFQSFTFOUJOH *G ZPVƊSF BO
FYQFSJFODFE QSPHSBNNFS UIJOL DBSFGVMMZ )PX NBOZ UJNFT
IBWF ZPV NFBOU GPS B MJTU UP OFWFS CF FNQUZ 5P HVBSBOUFF
UIJT BOE NBLF UIF UZQFT NPSF JOGPSNBUJWF XF VTF UZQFT MJLF
/PO&NQUZ
5IF QSPCMFN JT UIBU /PO&NQUZ IBT OP JEFOUJUZ WBMVF GPS
UIF DPNCJOJOH PQFSBUJPO mappend
JO .POPJE 4P XF LFFQ UIF
BTTPDJBUJWJUZ CVU ESPQ UIF JEFOUJUZ WBMVF BOE JUT MBXT PG MFǒ BOE
SJHIU JEFOUJUZ 5IJT JT XIBU JOUSPEVDFT UIF OFFE GPS BOE JEFB
$)"15&3  .0/0*% 4&.*(3061 

PG 4FNJHSPVQ GSPN B EBUBUZQF


5IF NPTU PCWJPVT XBZ UP TFF UIBU .POPJE JT TUSPOHFS UIBO
4FNJHSPVQ JT UP PCTFSWF UIBU JU IBT B TUSJDU TVQFSTFU PG UIF
PQFSBUJPOT BOE MBXT UIBU 4FNJHSPVQ QSPWJEFT "OZUIJOH XIJDI
JT B .POPJE JT CZ EFƶOJUJPO BMTP B TFNJHSPVQ 4PPO 4FNJHSPVQ
XJMM CF BEEFE UP ()$ƊT CBTF MJCSBSZ BOE XIFO JU JT 4FNJHSPVQ
XJMM UIFO CF B TVQFSDMBTT PG .POPJE

class Semigroup a => Monoid a where


...

&BSMJFS XF SFBTPOFE BCPVU UIF JOWFSTF SFMBUJPOTIJQ CFUXFFO


PQFSBUJPOT QFSNJUUFE PWFS B UZQF BOE UIF OVNCFS PG UZQFT UIBU
DBO TBUJTGZ 8F DBO TFF UIJT SFMBUJPOTIJQ CFUXFFO UIF OVNCFS
PG PQFSBUJPOT BOE MBXT BO BMHFCSB EFNBOET BOE UIF OVNCFS
PG EBUBUZQFT UIBU DBO QSPWJEF B MBX BCJEJOH JOTUBODF PG UIBU
BMHFCSB
*O UIF GPMMPXJOH FYBNQMF Ԑ DBO CF BOZUIJOH JO UIF VOJWFSTF
CVU UIFSF BSF OP PQFSBUJPOT PWFS JU ƈ XF DBO POMZ SFUVSO UIF
TBNF WBMVF

id :: a -> a

Ƒ /VNCFS PG UZQFT *OƶOJUF ƈ VOJWFSTBMMZ RVBOUJƶFE TP


JU DBO CF BOZ UZQF UIF FYQSFTTJPO BQQMZJOH UIF GVODUJPO
XBOUT
$)"15&3  .0/0*% 4&.*(3061 

Ƒ /VNCFS PG PQFSBUJPOT POF JG ZPV DBO DBMM JU BO PQFSBUJPO


+VTU SFGFSFODJOH UIF WBMVF ZPV XFSF QBTTFE

8JUI inc Ԑ OPX IBT BMM UIF PQFSBUJPOT GSPN /VN XIJDI MFUT
VT EP NPSF #VU UIBU BMTP NFBOT JUƊT OPX B ƶOJUF TFU PG UZQFT
UIBU DBO TBUJTGZ UIF /VN DPOTUSBJOU SBUIFS UIBO CFJOH TUSJDUMZ
BOZ UZQF JO UIF VOJWFSTF

inc :: Num a => a -> a

Ƒ /VNCFS PG UZQFT BOZUIJOH UIBU JNQMFNFOUT /VN ;FSP


UP NBOZ

Ƒ /VNCFS PG PQFSBUJPOT  NFUIPET JO /VN

*O UIF OFYU FYBNQMF XF LOPX JUƊT BO *OUFHFS XIJDI HJWFT VT


NBOZ NPSF PQFSBUJPOT UIBO KVTU B /VN JOTUBODF

somethingInt :: Int -> Int

Ƒ /VNCFS PG UZQFT POF ƈ KVTU Int

Ƒ /VNCFS PG PQFSBUJPOT DPOTJEFSBCMZ NPSF UIBO  *O


BEEJUJPO UP /VN *OU IBT JOTUBODFT PG #PVOEFE &OVN
&R *OUFHSBM 0SE 3FBE 3FBM BOE 4IPX 0O UPQ PG UIBU
ZPV DBO XSJUF BSCJUSBSZ GVODUJPOT UIBU QBUUFSO NBUDI PO
DPODSFUF UZQFT BOE SFUVSO BSCJUSBSZ WBMVFT JO UIBU TBNF
UZQF BT UIF SFTVMU 1PMZNPSQIJTN JTOƊU POMZ VTFGVM GPS
$)"15&3  .0/0*% 4&.*(3061 

SFVTJOH DPEF JUƊT BMTP VTFGVM GPS FYQSFTTJOH JOUFOU UISPVHI


QBSBNFUSJDJUZ TP UIBU QFPQMF SFBEJOH UIF DPEF LOPX XIBU
XF NFBOU UP BDDPNQMJTI

8IFO .POPJE JT UPP TUSPOH PS NPSF UIBO XF OFFE XF


DBO VTF 4FNJHSPVQ *G ZPVƊSF XPOEFSJOH XIBUƊT XFBLFS UIBO
4FNJHSPVQ UIF VTVBM OFYU TUFQ JT SFNPWJOH UIF BTTPDJBUJWJUZ
SFRVJSFNFOU HJWJOH ZPV B NBHNB *UƊT OPU MJLFMZ UP DPNF VQ
JO EBZ UP EBZ )BTLFMM CVU ZPV DBO TPVOE DPPM BU QSPHSBNNJOH
DPOGFSFODFT GPS LOPXJOH XIBUƊT XFBLFS UIBO B TFNJHSPVQ TP
QPDLFU UIBU POF GPS UIF QVC

 $IBQUFS FYFSDJTFT


4FNJHSPVQ FYFSDJTFT
(JWFO B EBUBUZQF JNQMFNFOU UIF 4FNJHSPVQ JOTUBODF "EE
4FNJHSPVQ DPOTUSBJOUT UP UZQF WBSJBCMFT XIFSF OFFEFE 6TF
UIF 4FNJHSPVQ DMBTT GSPN UIF TFNJHSPVQT MJCSBSZ PS XSJUF ZPVS
PXO 8IFO XF VTF <> XF NFBO UIF JOƶY NBQQFOE GSPN UIF
4FNJHSPVQ UZQFDMBTT

/PUF 8FƊSF OPU BMXBZT HPJOH UP EFSJWF FWFSZ JOTUBODF ZPV


NBZ XBOU PS OFFE JO UIF EBUBUZQFT XF QSPWJEF GPS FYFSDJTFT
8F FYQFDU ZPV UP LOPX XIBU ZPV OFFE BOE UP UBLF DBSF PG JU
ZPVSTFMG CZ UIJT QPJOU
$)"15&3  .0/0*% 4&.*(3061 

 7BMJEBUF BMM PG ZPVS JOTUBODFT XJUI 2VJDL$IFDL 4JODF


4FNJHSPVQƊT POMZ MBX JT BTTPDJBUJWJUZ UIBUƊT UIF POMZ QSPQ
FSUZ ZPV OFFE UP SFVTF ,FFQ JO NJOE UIBU ZPVƊMM QP
UFOUJBMMZ OFFE UP JNQPSU UIF NPEVMFT GPS .POPJE BOE
4FNJHSPVQ BOE UP BWPJE OBNJOH DPOƷJDUT GPS UIF ( 

EFQFOEJOH PO ZPVS WFSTJPO PG ()$

data Trivial = Trivial deriving (Eq, Show)

instance Semigroup Trivial where


_ <> _ = undefined

instance Arbitrary Trivial where


arbitrary = return Trivial

semigroupAssoc :: (Eq m, Semigroup m) => m -> m -> m -> Bool


semigroupAssoc a b c = (a <> (b <> c)) == ((a <> b) <> c)

type TrivialAssoc = Trivial -> Trivial -> Trivial -> Bool

main :: IO ()
main =
quickCheck (semigroupAssoc :: TrivialAssoc)

 newtype Identity a = Identity a


$)"15&3  .0/0*% 4&.*(3061 

 data Two a b = Two a b

)JOU "TL GPS BOPUIFS Semigroup JOTUBODF

 data Three a b c = Three a b c

 data Four a b c d = Four a b c d

 newtype BoolConj =
BoolConj Bool

8IBU JU TIPVME EP

Prelude> (BoolConj True) <> (BoolConj True)


BoolConj True
Prelude> (BoolConj True) <> (BoolConj False)
BoolConj False

 newtype BoolDisj =
BoolDisj Bool

8IBU JU TIPVME EP

Prelude> (BoolDisj True) <> (BoolDisj True)


BoolDisj True
Prelude> (BoolDisj True) <> (BoolDisj False)
BoolDisj True
$)"15&3  .0/0*% 4&.*(3061 

 data Or a b =
Fst a
| Snd b

5IF 4FNJHSPVQ GPS Or TIPVME IBWF UIF GPMMPXJOH CFIBWJPS


8F DBO UIJOL PG UIJT BT IBWJOH B ƌTUJDLZƍ Snd WBMVF XIFSF
JUƊMM IPME POUP UIF ƶSTU Snd WBMVF XIFO BOE JG POF JT QBTTFE
BT BO BSHVNFOU 5IJT JT TJNJMBS UP UIF First' Monoid ZPV
XSPUF FBSMJFS

Prelude> Fst 1 <> Snd 2


Snd 2
Prelude> Fst 1 <> Fst 2
Fst 2
Prelude> Snd 1 <> Fst 2
Snd 1
Prelude> Snd 1 <> Snd 2
Snd 1

 ,FFQ JO NJOE ZPV XPOƊU CF BCMF UP FBTJMZ UFTU BTTPDJBUJWJUZ


GPS Combine CFDBVTF JU DPOUBJOT GVODUJPOT

newtype Combine a b =
Combine { unCombine :: (a -> b) }

8IBU JU TIPVME EP


$)"15&3  .0/0*% 4&.*(3061 

Prelude> let f = Combine $ \n -> Sum (n + 1)


Prelude> let g = Combine $ \n -> Sum (n - 1)
Prelude> unCombine (f <> g) $ 0
Sum {getSum = 0}
Prelude> unCombine (f <> g) $ 1
Sum {getSum = 2}
Prelude> unCombine (f <> f) $ 1
Sum {getSum = 4}
Prelude> unCombine (g <> f) $ 1
Sum {getSum = 2}

)JOU 5IJT GVODUJPO XJMM FWFOUVBMMZ CF BQQMJFE UP B TJOHMF


WBMVF PG UZQF Ԑ #VU ZPVƊMM IBWF NVMUJQMF GVODUJPOT UIBU
DBO QSPEVDF B WBMVF PG UZQF ԑ )PX EP XF DPNCJOF NVMUJ
QMF WBMVFT TP XF IBWF B TJOHMF ԑ 5IJT POF XJMM QSPCBCMZ
CF USJDLZ 3FNFNCFS UIBU UIF UZQF PG UIF WBMVF JOTJEF
PG $PNCJOF JT UIBU PG B GVODUJPO *G ZPV DBOƊU ƶHVSF PVU
$P"SCJUSBSZ EPOƊU XPSSZ BCPVU 2VJDL$IFDLJOH UIJT POF

 newtype Comp a =


Comp { unComp :: (a -> a) }

)JOU 8F DBO EP TPNFUIJOH UIBU TFFNT B MJUUMF NPSF TQF


DJƶD BOE OBUVSBM UP GVODUJPOT OPX UIBU UIF JOQVU BOE PVU
QVU UZQFT BSF UIF TBNF
$)"15&3  .0/0*% 4&.*(3061 

 -- Look familiar?

data Validation a b =
Failure a | Success b
deriving (Eq, Show)

instance Semigroup a =>


Semigroup (Validation a b) where
(<>) = undefined

 -- Validation with a Semigroup


-- that does something different

newtype AccumulateRight a b =
AccumulateRight (Validation a b)
deriving (Eq, Show)

instance Semigroup b =>


Semigroup (AccumulateRight a b) where
(<>) = undefined
$)"15&3  .0/0*% 4&.*(3061 

 -- Validation with a Semigroup


-- that does something more

newtype AccumulateBoth a b =
AccumulateBoth (Validation a b)
deriving (Eq, Show)

instance (Semigroup a, Semigroup b) =>


Semigroup (AccumulateBoth a b) where
(<>) = undefined

.POPJE FYFSDJTFT
(JWFO B EBUBUZQF JNQMFNFOU UIF .POPJE JOTUBODF "EE .POPJE
DPOTUSBJOUT UP UZQF WBSJBCMFT XIFSF OFFEFE 'PS UIF EBUBUZQFT
ZPVƊWF BMSFBEZ JNQMFNFOUFE 4FNJHSPVQ JOTUBODFT GPS ZPV
KVTU OFFE UP ƶHVSF PVU XIBU UIF JEFOUJUZ WBMVF JT

 "HBJO WBMJEBUF BMM PG ZPVS JOTUBODFT XJUI 2VJDL$IFDL


&YBNQMF TDBƵPME JT QSPWJEFE GPS UIF 5SJWJBM UZQF
$)"15&3  .0/0*% 4&.*(3061 

data Trivial = Trivial deriving (Eq, Show)

instance Semigroup Trivial where


(<>) = undefined

instance Monoid Trivial where


mempty = undefined
mappend = (<>)

type TrivialAssoc = Trivial -> Trivial -> Trivial -> Bool

main :: IO ()
main = do
quickCheck (semigroupAssoc :: TrivialAssoc)
quickCheck (monoidLeftIdentity :: Trivial -> Bool)
quickCheck (monoidRightIdentity :: Trivial -> Bool)

 newtype Identity a = Identity a deriving Show

 data Two a b = Two a b deriving Show

 newtype BoolConj =
BoolConj Bool

8IBU JU TIPVME EP

Prelude> (BoolConj True) `mappend` mempty


$)"15&3  .0/0*% 4&.*(3061 

BoolConj True
Prelude> mempty `mappend` (BoolConj False)
BoolConj False

 newtype BoolDisj =
BoolDisj Bool

8IBU JU TIPVME EP

Prelude> (BoolDisj True) `mappend` mempty


BoolDisj True
Prelude> mempty `mappend` (BoolDisj False)
BoolDisj False

 newtype Combine a b =
Combine { unCombine :: (a -> b) }

8IBU JU TIPVME EP

Prelude> let f = Combine $ \n -> Sum (n + 1)


Prelude> unCombine (mappend f mempty) $ 1
Sum {getSum = 2}

 )JOU 8F DBO EP TPNFUIJOH UIBU TFFNT B MJUUMF NPSF TQF


DJƶD BOE OBUVSBM UP GVODUJPOT OPX UIBU UIF JOQVU BOE PVU
QVU UZQFT BSF UIF TBNF
$)"15&3  .0/0*% 4&.*(3061 

newtype Comp a =
Comp (a -> a)

 5IJT OFYU FYFSDJTF XJMM JOWPMWF EPJOH TPNFUIJOH UIBU XJMM


GFFM B CJU VOOBUVSBM TUJMM BOE ZPV NBZ ƶOE JU EJƸDVMU *G ZPV
HFU JU BOE ZPV IBWFOƊU EPOF NVDI '1 PS )BTLFMM CFGPSF
HFU ZPVSTFMG B OJDF CFWFSBHF 8FƊSF HPJOH UP UPTT ZPV
UIF JOTUBODF EFDMBSBUJPO TP ZPV EPOƊU DIVSO PO B NJTTJOH
.POPJE DPOTUSBJOU ZPV EJEOƊU LOPX ZPV OFFEFE

newtype Mem s a =
Mem {
runMem :: s -> (a,s)
}

instance Monoid a => Monoid (Mem s a) where


mempty = undefined
mappend = undefined

(JWFO UIF GPMMPXJOH DPEF


$)"15&3  .0/0*% 4&.*(3061 

f' = Mem $ \s -> ("hi", s + 1)

main = do
print $ runMem (f' <> mempty) 0
print $ runMem (mempty <> f') 0
print $ (runMem mempty 0 :: (String, Int))
print $ runMem (f' <> mempty) 0 == runMem f' 0
print $ runMem (mempty <> f') 0 == runMem f' 0

" DPSSFDU .POPJE GPS .FN TIPVME HJWFO UIF BCPWF DPEF
HFU UIF GPMMPXJOH PVUQVU

Prelude> main
("hi",1)
("hi",1)
("",0)
True
True

.BLF DFSUBJO ZPVS JOTUBODF IBT PVUQVU MJLF UIF BCPWF UIJT
JT TBOJUZDIFDLJOH UIF .POPJE JEFOUJUZ MBXT GPS ZPV *UƊT
OPU B QSPPG BOE JUƊT OPU FWFO BT HPPE BT RVJDLDIFDLJOH
CVU JUƊMM DBUDI UIF NPTU DPNNPO NJTUBLFT QFPQMF NBLF *G
ZPVƊE MJLF UP MFBSO IPX UP HFOFSBUF GVODUJPOT XJUI 2VJDL$IFDL
OPU KVTU WBMVFT MPPL BU CoArbitrary JO 2VJDL$IFDLƊT EPDV
NFOUBUJPO
$)"15&3  .0/0*% 4&.*(3061 

*UƊT OPU B USJDL BOE ZPV EPOƊU OFFE B .POPJE GPS Ԣ :FT
TVDI B .POPJE DBO BOE EPFT FYJTU )JOU DIBJO UIF T WBMVFT
GSPN POF GVODUJPO UP UIF PUIFS :PVƊMM XBOU UP DIFDL UIF
JEFOUJUZ MBXT BT B DPNNPO ƶSTU BUUFNQU XJMM CSFBL UIFN

 %FƶOJUJPOT
 " NPOPJE JT B TFU UIBU JT DMPTFE VOEFS BO BTTPDJBUJWF CJOBSZ
PQFSBUJPO BOE IBT BO JEFOUJUZ FMFNFOU $MPTFE JT UIF QPTI
NBUIFNBUJDBM XBZ PG TBZJOH JUƊT UZQF JT

mappend :: m -> m -> m

4VDI UIBU ZPVS BSHVNFOUT BOE PVUQVU XJMM BMXBZT JOIBCJU


UIF TBNF UZQF TFU


 " TFNJHSPVQ JT B TFU UIBU JT DMPTFE VOEFS BO BTTPDJBUJWF


CJOBSZ PQFSBUJPO ƈ BOE OPUIJOH FMTF

 -BXT BSF SVMFT BCPVU IPX BO BMHFCSB PS TUSVDUVSF TIPVME


CFIBWF 5IFTF BSF OFFEFE JO QBSU UP NBLF BCTUSBDUJPO PWFS
UIF DPNNPOBMJUJFT PG EJƵFSFOU JOTUBOUJBUJPOT PG UIF TBNF
TPSU PG BMHFCSB QPTTJCMF BOE QSBDUJDBM 5IJT JT DSJUJDBM UP
IBWJOH BCTUSBDUJPOT XIJDI BSFOƊU VOQMFBTBOUMZ TVSQSJTJOH

 "O BMHFCSB JT WBSJPVTMZ


$)"15&3  .0/0*% 4&.*(3061 

B
4DIPPM BMHFCSB TVDI BT UIBU UBVHIU JO QSJNBSZ BOE
TFDPOEBSZ TDIPPM 5IJT VTVBMMZ FOUBJMT UIF CBMBODJOH
PG QPMZOPNJBM FRVBUJPOT BOE MFBSOJOH IPX GVODUJPOT
BOE HSBQIT XPSL
C
5IF TUVEZ PG OVNCFS TZTUFNT BOE PQFSBUJPOT XJUIJO
UIFN 5IJT XJMM UZQJDBMMZ FOUBJM B QBSUJDVMBS BSFB TVDI
BT HSPVQT PS SJOHT 5IJT JT XIBU NBUIFNBUJDJBOT DPN
NPOMZ NFBO CZ ƌBMHFCSBƍ 5IJT JT TPNFUJNFT EJTBN
CJHVBUFE CZ CFJOH SFGFSSFE UP BT BCTUSBDU BMHFCSB
D
" UIJSE BOE ƶOBM XBZ BMHFCSB JT VTFE JT UP SFGFS UP B
WFDUPS TQBDF PWFS B ƶFME XJUI B NVMUJQMJDBUJPO

8IFO )BTLFMMFST SFGFS UP BMHFCSBT UIFZƊSF VTVBMMZ UBMLJOH


BCPVU B TPNFXIBU JOGPSNBM OPUJPO PG PQFSBUJPOT PWFS
B UZQF BOE JUT MBXT TVDI BT XJUI TFNJHSPVQT NPOPJET
HSPVQT TFNJSJOHT BOE SJOHT

 'PMMPXVQ SFTPVSDFT


 "MHFCSBJD TUSVDUVSF 4JNQMF &OHMJTI 8JLJQFEJB

 )BTLFMM .POPJET BOE 5IFJS 6TFT %BO 1JQPOJ


$IBQUFS 

'VODUPS

-JǒJOH JT UIF ƍDIFBU


NPEFƍ PG UZQF UFUSJT

.JDIBFM /FBMF


$)"15&3  '6/$503 

 'VODUPS
*O UIF MBTU DIBQUFS PO .POPJE XF TBX XIBU JU NFBOT UP UBML
BCPVU BO BMHFCSB BOE UVSO UIBU JOUP B UZQFDMBTT 5IJT DIBQUFS
BOE UIF UXP UIBU GPMMPX PO "QQMJDBUJWF BOE .POBE XJMM CF PO
B TJNJMBS UPQJD &BDI PG UIFTF BMHFCSBT JT NPSF QPXFSGVM UIBO
UIF MBTU CVU UIF HFOFSBM DPODFQU IFSF XJMM SFNBJO UIF TBNF
XF BCTUSBDU PVU B DPNNPO QBUUFSO NBLF DFSUBJO JU GPMMPXT
TPNF MBXT HJWF JU BO BXFTPNF OBNF BOE XPOEFS IPX XF FWFS
MJWFE XJUIPVU JU .POBET TPSU PG TUFBM UIF )BTLFMM TQPUMJHIU
CVU ZPV DBO EP NPSF XJUI 'VODUPS BOE "QQMJDBUJWF UIBO NBOZ
QFPQMF SFBMJ[F "MTP VOEFSTUBOEJOH 'VODUPS BOE "QQMJDBUJWF
JT JNQPSUBOU UP B EFFQ VOEFSTUBOEJOH PG .POBE
5IJT DIBQUFS JT BMM BCPVU 'VODUPS BOE 'VODUPS JT BMM BCPVU B
QBUUFSO PG NBQQJOH PWFS TUSVDUVSF 8F TBX fmap XBZ CBDL JO
-JTUT BOE OPUFE UIBU JU XPSLFE KVTU UIF TBNF BT map CVU XF BMTP
TBJE CBDL UIFO UIBU UIF EJƵFSFODF JT UIBU ZPV DBO VTF fmap XJUI
TUSVDUVSFT UIBU BSFOƊU MJTUT /PX XF XJMM CFHJO UP TFF XIBU UIBU
NFBOT
5IF HSFBU MPHJDJBO 3VEPMG $BSOBQ BQQFBST UP IBWF CFFO UIF
ƶSTU QFSTPO UP VTF UIF XPSE ƉGVODUPSƊ JO UIF T )F JOWFOUFE
UIF XPSE UP EFTDSJCF DFSUBJO UZQFT PG HSBNNBUJDBM GVODUJPO
XPSET BOE MPHJDBM PQFSBUJPOT PWFS TFOUFODFT PS QISBTFT 'VOD
UPST BSF DPNCJOBUPST UIFZ UBLF B TFOUFODF PS QISBTF BT JOQVU
BOE QSPEVDF B TFOUFODF PS QISBTF BT BO PVUQVU XJUI TPNF
MPHJDBM PQFSBUJPO BQQMJFE UP UIF XIPMF 'PS FYBNQMF OFHBUJPO
$)"15&3  '6/$503 

JT B GVODUPS JO UIJT TFOTF CFDBVTF XIFO OFHBUJPO JT BQQMJFE


UP B TFOUFODF Ӷ JU QSPEVDFT UIF OFHBUFE WFSTJPO મӶ BT BO
PVUQVU *U MJǒT UIF DPODFQU PG OFHBUJPO PWFS UIF FOUJSF TFOUFODF
PS QISBTF TUSVDUVSF XJUIPVU DIBOHJOH UIF JOUFSOBM TUSVDUVSF
:FT JO &OHMJTI UIF OFHBUJPO XPSE PǒFO BQQFBST JOTJEF UIF
TFOUFODF OPU PO UIF PVUTJEF CVU IF XBT B MPHJDJBO BOE VODPO
DFSOFE XJUI IPX OPSNBM IVNBOT QSPEVDFE TVDI QFEFTUSJBO
UIJOHT BT TQPLFO TFOUFODFT *O MPHJD UIF OFHBUJPO PQFSBUPS JT
UZQJDBMMZ XSJUUFO BT B QSFƶY BT BCPWF

5IJT DIBQUFS XJMM JODMVEF

Ƒ UIF SFUVSO PG UIF IJHIFSLJOEFE UZQFT

Ƒ GNBQT HBMPSF BOE OPU KVTU PO MJTUT

Ƒ OP NPSF EJHSFTTJPOT BCPVU EVTUZ MPHJDJBOT

Ƒ XPSET BCPVU UZQFDMBTTFT BOE DPOTUSVDUPS DMBTTFT

Ƒ QVOT CBTFE PO (FPSHF $MJOUPO NVTJD QSPCBCMZ

 8IBUƊT B GVODUPS


" GVODUPS JT B XBZ UP BQQMZ B GVODUJPO PWFS PS BSPVOE TPNF
TUSVDUVSF UIBU XF EPOƊU XBOU UP BMUFS 5IBU JT XF XBOU UP BQQMZ
UIF GVODUJPO UP UIF WBMVF UIBU JT ƌJOTJEFƍ TPNF TUSVDUVSF BOE
MFBWF UIF TUSVDUVSF BMPOF 5IBUƊT XIZ JU JT NPTU DPNNPO UP
JOUSPEVDF GVODUPS CZ XBZ PG GNBQQJOH PWFS MJTUT BT XF EJE
$)"15&3  '6/$503 

CBDL JO UIF -JTUT DIBQUFS 5IF GVODUJPO HFUT BQQMJFE UP FBDI


WBMVF JOTJEF UIF MJTU BOE UIF MJTU TUSVDUVSF SFNBJOT " HPPE XBZ
UP SFMBUF ƌOPU BMUFSJOH UIF TUSVDUVSFƍ UP MJTUT JT UIBU UIF MFOHUI
PG UIF MJTU BǒFS NBQQJOH B GVODUJPO PWFS JU XJMM BMXBZT CF UIF
TBNF /P FMFNFOUT BSF SFNPWFE PS BEEFE POMZ USBOTGPSNFE
5IF UZQFDMBTT Functor HFOFSBMJ[FT UIJT QBUUFSO TP UIBU XF DBO
VTF UIBU CBTJD JEFB XJUI NBOZ UZQFT PG TUSVDUVSF OPU KVTU MJTUT
'VODUPS JT JNQMFNFOUFE JO )BTLFMM XJUI B UZQFDMBTT KVTU MJLF
.POPJE 0UIFS NFBOT PG JNQMFNFOUJOH JU BSF QPTTJCMF CVU
UIJT JT UIF NPTU DPOWFOJFOU XBZ UP EP TP 5IF EFƶOJUJPO PG UIF
'VODUPS UZQFDMBTT JO )BTLFMM MPPLT MJLF UIJT

class Functor f where


fmap :: (a -> b) -> f a -> f b

/PX MFUƊT EJTTFDU UIJT B CJU

class Functor f where


[1] [2] [3] [4]
fmap :: (a -> b) -> f a -> f b
[5] [6] [7] [8]

 class JT UIF LFZXPSE UP CFHJO UIF EFƶOJUJPO PG B UZQFDMBTT

 'VODUPS JT UIF OBNF PG UIF UZQFDMBTT XF BSF EFƶOJOH

 5ZQFDMBTTFT JO )BTLFMM VTVBMMZ SFGFS UP TPNF TPSU PG UZQF


5IF MFUUFST UIFNTFMWFT BT XJUI UZQF WBSJBCMFT JO UZQF TJH
$)"15&3  '6/$503 

OBUVSFT EP OPU NFBO BOZUIJOH TQFDJBM f JT B DPOWFOUJPOBM


MFUUFS UP DIPPTF XIFO SFGFSSJOH UP UZQFT UIBU IBWF GVODUP
SJBM TUSVDUVSF 5IF f NVTU CF UIF TBNF f UISPVHIPVU UIF
UZQFDMBTT EFƶOJUJPO

 5IF where LFZXPSE FOET UIF EFDMBSBUJPO PG UIF UZQFDMBTT


OBNF BOE BTTPDJBUFE UZQFT "ǒFS UIF where UIF PQFSBUJPOT
QSPWJEFE CZ UIF UZQFDMBTT BSF MJTUFE

 8F CFHJO UIF EFDMBSBUJPO PG BO PQFSBUJPO OBNFE fmap

 5IF BSHVNFOU a -> b JT BOZ GVODUJPO JO )BTLFMM

 5IF BSHVNFOU f a JT B Functor ԕ UIBU UBLFT B UZQF BSHVNFOU


Ԑ 5IBU JT UIF ԕ JT B UZQF UIBU IBT BO JOTUBODF PG UIF Functor
UZQFDMBTT

 5IF SFUVSO WBMVF JT f b *U JT UIF TBNF f GSPN f a XIJMF


UIF UZQF BSHVNFOU ԑ QPTTJCMZ CVU OPU OFDFTTBSJMZ SFGFST UP B
EJƵFSFOU UZQF

#FGPSF XF EFMWF JOUP UIF EFUBJMT PG IPX UIJT UZQFDMBTT XPSLT


MFUƊT TFF fmap JO BDUJPO TP ZPV HFU B GFFM GPS XIBUƊT HPJOH PO ƶSTU
$)"15&3  '6/$503 

 5IFSFƊT B XIPMF MPU PG GNBQ HPJOH


SPVOE
8F IBWF TFFO fmap CFGPSF CVU XF IBWFOƊU VTFE JU NVDI FYDFQU
GPS XJUI MJTUT 8JUI MJTUT JU TFFNT UP EP UIF TBNF UIJOH BT map

Prelude> map (\x -> x > 3) [1..6]


[False,False,False,True,True,True]
Prelude> fmap (\x -> x > 3) [1..6]
[False,False,False,True,True,True]

-JTU JT PG DPVSTF POF UZQF UIBU JNQMFNFOUT UIF UZQFDMBTT


'VODUPS CVU JU TFFNT VOSFNBSLBCMF XIFO JU KVTU EPFT UIF TBNF
UIJOH BT map )PXFWFS -JTU JTOƊU UIF POMZ UZQF UIBU JNQMFNFOUT
'VODUPS BOE fmap DBO BQQMZ B GVODUJPO PWFS PS BSPVOE BOZ PG
UIPTF GVODUPSJBM TUSVDUVSFT XIJMF map DBOOPU

Prelude> map (+1) (Just 1)

Couldn't match expected type ‘[b]’


with actual type ‘Maybe a0’

Relevant bindings include it :: [b] (bound at 16:1)


In the second argument of ‘map’, namely ‘(Just 1)’
In the expression: map (+ 1) (Just 1)
$)"15&3  '6/$503 

Prelude> fmap (+1) (Just 1)


Just 2

*OUSJHVJOH 8IBU FMTF

--with a tuple!
Prelude> fmap (10/) (4, 5)
(4,2.0)

--with Either!
Prelude> fmap (++ ", Esq.") (Right "Chris Allen")
Right "Chris Allen, Esq."

8F DBO TFF IPX UIF UZQF PG fmap TQFDJBMJ[FT UP EJƵFSFOU


UZQFT IFSF

-- Functor f =>
fmap :: (a -> b) -> f a -> f b
:: (a -> b) -> [ ] a -> [ ] b
:: (a -> b) -> Maybe a -> Maybe b
:: (a -> b) -> Either e a -> Either e b
:: (a -> b) -> (e,) a -> (e,) b
:: (a -> b) -> Identity a -> Identity b
:: (a -> b) -> Constant e a -> Constant e b

:PV NBZ IBWF OPUJDFE JO UIF UVQMF BOE &JUIFS FYBNQMFT UIBU
UIF ƶSTU BSHVNFOUT MBCFMFE Ԕ JO UIF BCPWF DIBSU
BSF JHOPSFE
$)"15&3  '6/$503 

CZ fmap 8FƊMM UBML BCPVU XIZ UIBU JT JO KVTU B CJU -FUƊT ƶSTU UVSO
PVS BUUFOUJPO UP XIBU NBLFT B GVODUPS -BUFS XFƊMM DPNF CBDL
UP MPOHFS FYBNQMFT BOE FYQBOE PO UIJT DPOTJEFSBCMZ

 -FUƊT UBML BCPVU ԕ CBCZ


"T XF TBJE BCPWF UIF ԕ JO UIF UZQFDMBTT EFƶOJUJPO GPS Functor
NVTU CF UIF TBNF ԕ UISPVHIPVU UIF FOUJSF EFƶOJUJPO BOE JU
NVTU SFGFS UP B UZQF UIBU JNQMFNFOUT UIF UZQFDMBTT 5IJT TFD
UJPO EFUBJMT UIF QSBDUJDBM SBNJƶDBUJPOT PG UIPTF GBDUT
5IF ƶSTU UIJOH XF LOPX JT UIBU PVS ԕ IFSF NVTU IBWF UIF LJOE
* -> * 8F UBMLFE BCPVU IJHIFSLJOEFE UZQFT JO QSFWJPVT DIBQ
UFST BOE XF SFDBMM UIBU B UZQF DPOTUBOU PS B GVMMZ BQQMJFE UZQF
IBT UIF LJOE * " UZQF XJUI LJOE * -> * JT BXBJUJOH BQQMJDBUJPO
UP B UZQF DPOTUBOU PG LJOE *
8F LOPX UIBU UIF ԕ JO PVS 'VODUPS EFƶOJUJPO NVTU CF LJOE
* -> * GPS B DPVQMF PG SFBTPOT XIJDI XF XJMM ƶSTU EFTDSJCF BOE
UIFO EFNPOTUSBUF

 &BDI BSHVNFOU BOE SFTVMU


JO UIF UZQF TJHOBUVSF GPS B
GVODUJPO NVTU CF B GVMMZ BQQMJFE BOE JOIBCJUBCMF NPEVMP
7PJE FUD
UZQF &BDI BSHVNFOU NVTU IBWF UIF LJOE *

 5IF UZQF ԕ XBT BQQMJFE UP B TJOHMF BSHVNFOU JO UXP EJG


GFSFOU QMBDFT f a BOE f b 4JODF f a BOE f b NVTU FBDI
IBWF UIF LJOE * ԕ CZ JUTFMG NVTU CF LJOE * -> *
$)"15&3  '6/$503 

*UƊT FBTJFS UP TFF XIBU UIFTF NFBO JO QSBDUJDF CZ EFNPOTUSBU


JOH XJUI MPUT PG DPEF TP MFUƊT UFBS UIF SPPG PƵ UIJT TVDLFS

4IJOJOH TUBS DPNF JOUP WJFX


&WFSZ BSHVNFOU UP UIF UZQF DPOTUSVDUPS PG -> NVTU CF PG LJOE
* 8F DBO WFSJGZ UIJT TJNQMZ CZ RVFSZJOH LJOE PG UIF GVODUJPO
UZQF DPOTUSVDUPS GPS PVSTFMWFT

Prelude> :k (->)
(->) :: * -> * -> *

&BDI BSHVNFOU BOE SFTVMU PG FWFSZ GVODUJPO NVTU CF B UZQF


DPOTUBOU OPU B UZQF DPOTUSVDUPS (JWFO UIBU LOPXMFEHF XF
DBO LOPX TPNFUIJOH BCPVU 'VODUPS GSPN UIF UZQF PG fmap

class Functor f where


fmap :: (a -> b) -> f a -> f b
--has kind: * -> * -> *

5IF UZQF TJHOBUVSF PG fmap UFMMT VT UIBU UIF ԕ JOUSPEVDFE


CZ UIF DMBTT EFƶOJUJPO GPS 'VODUPS NVTU BDDFQU B TJOHMF UZQF
BSHVNFOU BOE UIVT CF PG LJOE * -> * 8F DBO EFUFSNJOF UIJT
FWFO XJUIPVU LOPXJOH BOZUIJOH BCPVU UIF UZQFDMBTT XIJDI
XFƊMM EFNPOTUSBUF XJUI TPNF NFBOJOHMFTT UZQFDMBTTFT
$)"15&3  '6/$503 

class Sumthin a where


s :: a -> a

class Else where


e :: b -> f (g a b c)

class Biffy where


slayer :: e a b -> (a -> c) -> (b -> d) -> e c d

-FUƊT EFDPOTUSVDU UIF QSFWJPVT DPVQMF PG FYBNQMFT

class Sumthin a where


s :: a -> a
-- [1] [1]

 5IF BSHVNFOU BOE SFTVMU UZQF BSF CPUI Ԑ 5IFSFƊT OPUIJOH


FMTF TP Ԑ IBT LJOE *

class Else where


e :: b -> f (g a b c)
-- [1] [2] [3]

 5IJT ԑ MJLF Ԑ JO UIF QSFWJPVT FYBNQMF TUBOET BMPOF BT UIF


ƶSTU BSHVNFOU UP (->) TP JU JT LJOE *

 )FSF ԕ JT UIF PVUFSNPTU UZQF DPOTUSVDUPS GPS UIF TFDPOE


BSHVNFOU UIF SFTVMU UZQF
PG (->) *U UBLFT B TJOHMF BSHV
$)"15&3  '6/$503 

NFOU UIF UZQF g a b c XSBQQFE JO QBSFOUIFTFT 5IVT ԕ


IBT LJOE * -> *

 "OE Ԗ JT BQQMJFE UP UISFF BSHVNFOUT Ԑ ԑ BOE Ԓ 5IBU NFBOT


JU JT LJOE * -> * -> * -> * XIFSF

-- using :: to denote kind signature


g :: * -> * -> * -> *

-- a, b, and c are each kind *

g :: * -> * -> * -> *


g a b c (g a b c)

class Biffy where


slayer :: e a b -> (a -> c) -> (b -> d) -> e c d
-- [1] [2] [3]

 'JSTU Ԕ JT BO BSHVNFOU UP (->) TP UIF BQQMJDBUJPO PG JUT


BSHVNFOUT NVTU SFTVMU JO LJOE * (JWFO UIBU BOE LOPXJOH
UIFSF BSF UXP BSHVNFOUT Ԑ BOE ԑ XF DBO EFUFSNJOF Ԕ JT
LJOE * -> * -> *

 5IJT Ԑ JT BO BSHVNFOU UP B GVODUJPO UIBU UBLFT OP BSHV


NFOUT JUTFMG TP JUƊT LJOE *

 5IF TUPSZ GPS Ԓ JT JEFOUJDBM IFSF KVTU JO BOPUIFS TQPU PG


UIF TBNF GVODUJPO
$)"15&3  '6/$503 

5IF LJOE DIFDLFS JT HPJOH UP GBJM PO UIF OFYU DPVQMF PG


FYBNQMFT

class Impish v where


impossibleKind :: v -> v a

class AlsoImp v where


nope :: v a -> v

3FNFNCFS UIBU UIF OBNF PG UIF WBSJBCMF CFGPSF UIF where


JO B UZQFDMBTT EFƶOJUJPO CJOET UIF PDDVSSFODFT PG UIBU OBNF
UISPVHIPVU UIF EFƶOJUJPO ()$ XJMM OPUJDF UIBU PVS ԥ TPNF
UJNFT IBT B UZQF BSHVNFOU BOE TPNFUJNFT OPU BOE JU XJMM DBMM
PVS CMVƵ JG XF BUUFNQU UP GFFE JU UIJT OPOTFOTF

‘v’ is applied to too many type arguments


In the type ‘v -> v a’
In the class declaration for ‘Impish’

Expecting one more argument to ‘v’


Expected a type, but ‘v’ has kind ‘k0 -> *’
In the type ‘v a -> v’
In the class declaration for ‘AlsoImp’

+VTU BT ()$ IBT UZQF JOGFSFODF JU BMTP IBT LJOE JOGFSFODF


"OE KVTU BT JU EPFT XJUI UZQFT JU DBO OPU POMZ JOGFS UIF LJOET
CVU BMTP WBMJEBUF UIBU UIFZƊSF DPOTJTUFOU BOE NBLF TFOTF
$)"15&3  '6/$503 

&YFSDJTFT #F ,JOE
(JWFO B UZQF TJHOBUVSF EFUFSNJOF UIF LJOET PG FBDI UZQF WBSJ
BCMF

 8IBUƊT UIF LJOE PG Ԑ

a -> a

 8IBU BSF UIF LJOET PG ԑ BOE ԉ 5IF ԉ JT DBQJUBMJ[FE PO


QVSQPTF

a -> b a -> T (b a)

 8IBUƊT UIF LJOE PG Ԓ

c a b -> c b a

" TIJOJOH TUBS GPS ZPV UP TFF


4P XIBU JG PVS UZQF JTOƊU IJHIFSLJOEFE -FUƊT USZ JU XJUI B UZQF
DPOTUBOU BOE TFF XIBU IBQQFOT
$)"15&3  '6/$503 

-- functors1.hs

data FixMePls =
FixMe
| Pls
deriving (Eq, Show)

instance Functor FixMePls where


fmap = error "it doesn't matter, it won't compile"

/PUJDF UIFSF BSF OP UZQF BSHVNFOUT BOZXIFSF ƈ FWFSZUIJOH


JT KVTU POF TIJOJOH LJOE
TUBS "OE JG XF MPBE UIJT ƶMF GSPN
()$J XFƊMM HFU UIF GPMMPXJOH FSSPS

Prelude> :l functors1.hs
[1 of 1] Compiling Main ( functors1.hs, interpreted )

functors1.hs:8:18:
The first argument of ‘Functor’ should have kind ‘* -> *’,
but ‘FixMePls’ has kind ‘*’
In the instance declaration for ‘Functor FixMePls’
Failed, modules loaded: none.

*O GBDU BTLJOH GPS B 'VODUPS GPS FixMePls EPFTOƊU SFBMMZ NBLF


TFOTF 5P TFF XIZ UIJT EPFTOƊU NBLF TFOTF DPOTJEFS UIF UZQFT
JOWPMWFE
$)"15&3  '6/$503 

-- Functor is:
fmap :: Functor f => (a -> b) -> f a -> f b

-- If we replace f with FixMePls


(a -> b) -> FixMePls a -> FixMePls b

-- But FixMePls doesn't take type arguments,


-- so this is really more like:
(FixMePls -> FixMePls) -> FixMePls -> FixMePls

5IFSFƊT OP UZQF DPOTUSVDUPS ԕ JO UIFSF 5IF NBYJNBMMZ


QPMZNPSQIJD WFSTJPO PG UIJT JT

(a -> b) -> a -> b

4P JO GBDU OPU IBWJOH B UZQF BSHVNFOU NFBOT UIJT JT KVTU

($) :: (a -> b) -> a -> b

8JUIPVU B UZQF BSHVNFOU UIJT JT NFSF GVODUJPO BQQMJDBUJPO

'VODUPS JT GVODUJPO BQQMJDBUJPO


8F KVTU TBX IPX USZJOH UP NBLF B 'VODUPS JOTUBODF GPS B UZQF
DPOTUBOU NFBOT ZPV KVTU IBWF GVODUJPO BQQMJDBUJPO #VU JO
GBDU fmap JT B TQFDJƶD TPSU PG GVODUJPO BQQMJDBUJPO -FUƊT MPPL BU
UIF UZQFT
$)"15&3  '6/$503 

fmap :: Functor f => (a -> b) -> f a -> f b

5IFSF JT BMTP BO JOƶY PQFSBUPS GPS fmap *G ZPVƊSF VTJOH BO


PMEFS WFSTJPO PG ()$ ZPV NBZ OFFE UP JNQPSU Data.Functor
JO PSEFS UP VTF JU JO UIF 3&1- 0G DPVSTF JU IBT UIF TBNF UZQF
BT UIF QSFƶY fmap

-- <$> is the infix alias for fmap:


(<$>) :: Functor f => (a -> b) -> f a -> f b

/PUJDF TPNFUIJOH

(<$>) :: Functor f => (a -> b) -> f a -> f b


($) :: (a -> b) -> a -> b

'VODUPS JT B UZQFDMBTT GPS GVODUJPO BQQMJDBUJPO ƌPWFSƍ PS


ƌUISPVHIƍ PS ƌQBTUƍ TPNF TUSVDUVSF f UIBU XF XBOU UP JHOPSF
BOE MFBWF VOUPVDIFE 8FƊMM FYQMBJO ƌMFBWF VOUPVDIFEƍ JO NPSF
EFUBJM MBUFS XIFO XF UBML BCPVU UIF 'VODUPS MBXT

" TIJOJOH TUBS GPS ZPV UP TFF XIBU ZPVS ԕ DBO


USVMZ CF
-FUƊT SFTVNF PVS FYQMPSBUJPO PG XIZ XF OFFE B IJHIFSLJOEFE
ԕ
*G XF BEE B UZQF BSHVNFOU UP UIF EBUBUZQF GSPN BCPWF XF
NBLF FixMePls JOUP B UZQF DPOTUSVDUPS BOE UIJT XJMM XPSL
$)"15&3  '6/$503 

-- functors2.hs

data FixMePls a =
FixMe
| Pls a
deriving (Eq, Show)

instance Functor FixMePls where


fmap = error "it doesn't matter, it won't compile"

/PX JUƊMM DPNQJMF

Prelude> :l code/functors2.hs
[1 of 1] Compiling Main
Ok, modules loaded: Main.

#VU XBJU XF EPOƊU OFFE UIF FSSPS BOZNPSF -FUƊT ƶY UIBU


Functor JOTUBODF
$)"15&3  '6/$503 

-- functors3.hs

data FixMePls a =
FixMe
| Pls a
deriving (Eq, Show)

instance Functor FixMePls where


fmap _ FixMe = FixMe
fmap f (Pls a) = Pls (f a)

-FUƊT TFF IPX PVS JOTUBODF MJOFT VQ XJUI UIF UZQF PG fmap

fmap :: Functor f => (a -> b) -> f a -> f b


fmap f (Pls a) = Pls (f a)
-- (a -> b) f a f b

8IJMF ԕ JT VTFE JO UIF UZQF PG fmap UP SFQSFTFOU UIF 'VODUPS


CZ DPOWFOUJPO JU JT BMTP DPOWFOUJPOBMMZ VTFE JO GVODUJPO EFG
JOJUJPOT UP OBNF BO BSHVNFOU UIBU JT JUTFMG B GVODUJPO %POƊU MFU
UIF OBNFT GPPM ZPV JOUP UIJOLJOH UIF ԕ JO PVS FixMePls JOTUBODF
JT UIF TBNF ԕ BT JO UIF 'VODUPS UZQFDMBTT EFƶOJUJPO
/PX PVS DPEF JT IBQQZNBLJOH

Prelude> :l code/functors3.hs
[1 of 1] Compiling Main
Ok, modules loaded: Main.
$)"15&3  '6/$503 

Prelude> fmap (+1) (Pls 1)


Pls 2

/PUJDF UIF GVODUJPO HFUT BQQMJFE PWFS BOE JOTJEF PG UIF


ƌTUSVDUVSFƍ /PX XF DBO CF TUSPOL )BTLFMM DPEFST BOE MJǒ CJH
IFBWZ GVODUJPOT PWFS BCTUSBDU TUSVDUVSF
0LBZ MFUƊT NBLF BOPUIFS NJTUBLF GPS UIF TBLF PG FYQMJDJU
OFTT 8IBU JG XF DIBOHF UIF UZQF PG PVS 'VODUPS JOTUBODF GSPN
FixMePls UP FixMePls a

-- functors4.hs

data FixMePls a =
FixMe
| Pls a
deriving (Eq, Show)

instance Functor (FixMePls a) where


fmap _ FixMe = FixMe
fmap f (Pls a) = Pls (f a)

/PUJDF XF EJEOƊU DIBOHF UIF UZQF JU TUJMM POMZ UBLFT POF


BSHVNFOU #VU OPX UIBU BSHVNFOU JT QBSU PG UIF ԕ TUSVDUVSF *G
XF MPBE UIJT JMMDPODFJWFE DPEF

Prelude> :l functors4.hs

ƌ4USPOLƍ NFBOT 4530/,
$)"15&3  '6/$503 

[1 of 1] Compiling Main

functors4.hs:8:19:
The first argument of ‘Functor’ should have kind ‘* -> *’,
but ‘FixMePls a’ has kind ‘*’
In the instance declaration for ‘Functor (FixMePls a)’
Failed, modules loaded: none.

8F HFU UIF TBNF FSSPS BT FBSMJFS CFDBVTF BQQMZJOH UIF UZQF


DPOTUSVDUPS HBWF VT TPNFUIJOH PG LJOE * GSPN UIF PSJHJOBM LJOE
PG * -> *

5ZQFDMBTTFT BOE DPOTUSVDUPS DMBTTFT


:PV NBZ IBWF JOJUJBMMZ QBVTFE PO UIF UZQF DPOTUSVDUPS ԕ JO
UIF EFƶOJUJPO PG 'VODUPS IBWJOH LJOE * -> * ƈ UIJT JT RVJUF
OBUVSBM *O GBDU FBSMJFS WFSTJPOT PG )BTLFMM EJEOƊU IBWF B GBDJMJUZ
GPS FYQSFTTJOH UZQFDMBTTFT JO UFSNT PG IJHIFSLJOEFE UZQFT
BU BMM 5IJT XBT EFWFMPQFE CZ .BSL 1 +POFT XIJMF IF XBT
XPSLJOH PO BO JNQMFNFOUBUJPO PG )BTLFMM DBMMFE (PGFS 5IJT
XPSL HFOFSBMJ[FE UZQFDMBTTFT GSPN CFJOH VTBCMF POMZ XJUI
UZQFT PG LJOE * BMTP DBMMFE UZQF DPOTUBOUT
UP CFJOH VTBCMF XJUI
IJHIFSLJOEFE UZQFT DBMMFE UZQF DPOTUSVDUPST BT XFMM

" TZTUFN PG DPOTUSVDUPS DMBTTFT PWFSMPBEJOH BOE JNQMJDJU IJHIFSPSEFS QPMZNPS
QIJTN
http://www.cs.tufts.edu/~nr/cs257/archive/mark-jones/fpca93.pdf
$)"15&3  '6/$503 

*O )BTLFMM UIF UXP VTF DBTFT IBWF CFFO NFSHFE TVDI UIBU
XF EPOƊU DBMM PVU DPOTUSVDUPS DMBTTFT BT CFJOH TFQBSBUF GSPN
UZQFDMBTTFT CVU XF UIJOL JUƊT VTFGVM UP IJHIMJHIU UIBU TPNFUIJOH
TJHOJƶDBOU IBT IBQQFOFE IFSF /PX XF IBWF B NFBOT PG UBMLJOH
BCPVU UIF DPOUFOUT PG UZQFT JOEFQFOEFOUMZ GSPN UIF UZQF UIBU
TUSVDUVSFT UIPTF DPOUFOUT 5IBUƊT XIZ XF DBO IBWF TPNFUIJOH
MJLF fmap UIBU BMMPXT VT UP BMUFS UIF DPOUFOUT PG B WBMVF XJUIPVU
BMUFSJOH UIF TUSVDUVSF B MJTU PS B +VTU
BSPVOE UIF WBMVF

 'VODUPS -BXT


*OTUBODFT PG UIF 'VODUPS UZQFDMBTT TIPVME BCJEF CZ UXP CBTJD
MBXT 6OEFSTUBOEJOH UIFTF MBXT JT DSJUJDBM GPS VOEFSTUBOEJOH
'VODUPS BOE XSJUJOH UZQFDMBTT JOTUBODFT UIBU BSF DPNQPTBCMF
BOE FBTZ UP SFBTPO BCPVU

*EFOUJUZ
5IF ƶSTU MBX JT UIF MBX PG JEFOUJUZ

fmap id == id

*G XF fmap UIF JEFOUJUZ GVODUJPO JU TIPVME IBWF UIF TBNF


SFTVMU BT QBTTJOH PVS WBMVF UP JEFOUJUZ 8F TIPVMEOƊU CF DIBOH
JOH BOZ PG UIF PVUFS TUSVDUVSF ԕ UIBU XFƊSF NBQQJOH PWFS CZ
NBQQJOH id 5IBUƊT XIZ JUƊT UIF TBNF BT id *G XF EJEOƊU SFUVSO
$)"15&3  '6/$503 

B OFX WBMVF JO UIF a -> b GVODUJPO NBQQFE PWFS UIF TUSVDUVSF


UIFO OPUIJOH TIPVMEƊWF DIBOHFE

Prelude> fmap id "Hi Julie"


"Hi Julie"
Prelude> id "Hi Julie"
"Hi Julie"

5SZ JU PVU PO B GFX EJƵFSFOU TUSVDUVSFT BOE DIFDL GPS ZPVS


TFMG

$PNQPTJUJPO
5IF TFDPOE MBX GPS 'VODUPS JT UIF MBX PG DPNQPTJUJPO

fmap (f . g) == fmap f . fmap g

5IJT DPODFSOT UIF DPNQPTBCJMJUZ PG fmap *G XF DPNQPTF


UXP GVODUJPOT ԕ BOE Ԗ BOE fmap UIBU PWFS TPNF TUSVDUVSF XF
TIPVME HFU UIF TBNF SFTVMU BT JG XF GNBQQFE UIFN BOE UIFO
DPNQPTFE UIFN

Prelude> fmap ((+1) . (*2)) [1..5]


[3,5,7,9,11]
Prelude> fmap (+1) . fmap (*2) $ [1..5]
[3,5,7,9,11]

*G BO JNQMFNFOUBUJPO PG fmap EPFTOƊU EP UIBU JUƊT B CSPLFO


GVODUPS
$)"15&3  '6/$503 

4USVDUVSF QSFTFSWBUJPO
#PUI PG UIFTF MBXT UPVDI PO UIF FTTFOUJBM SVMF UIBU GVODUPST
NVTU CF TUSVDUVSF QSFTFSWJOH
"MM XFƊSF BMMPXFE UP LOPX JO UIF UZQF BCPVU PVS JOTUBODF PG
'VODUPS JNQMFNFOUFE CZ ԕ JT UIBU JU JNQMFNFOUT 'VODUPS

fmap :: Functor f => (a -> b) -> f a -> f b

5IF ԕ JT DPOTUSBJOFE CZ UIF UZQFDMBTT 'VODUPS CVU UIBU JT BMM


XF LOPX BCPVU JUT UZQF GSPN UIJT EFƶOJUJPO "T XFƊWF TFFO XJUI
UZQFDMBTTDPOTUSBJOFE QPMZNPSQIJTN UIJT TUJMM BMMPXT JU UP CF
BOZ UZQF UIBU IBT BO JOTUBODF PG 'VODUPS 5IF DPSF PQFSBUJPO
UIBU UIJT UZQFDMBTT QSPWJEFT GPS UIFTF UZQFT JT fmap #FDBVTF UIF
ԕ QFSTJTUT UISPVHI UIF UZQF PG fmap XIBUFWFS UIF UZQF JT XF
LOPX JU NVTU CF B UZQF UIBU DBO UBLF BO BSHVNFOU BT JO f a BOE
f b BOE UIBU JU XJMM CF UIF ƌTUSVDUVSFƍ XFƊSF MJǒJOH UIF GVODUJPO
PWFS XIFO XF BQQMZ JU UP UIF WBMVF JOTJEF

 5IF (PPE UIF #BE BOE UIF 6HMZ


8FƊMM HFU B CFUUFS QJDUVSF PG XIBU JU NFBOT GPS 'VODUPS JOTUBODFT
UP CF MBXBCJEJOH PS MBXCSFBLJOH CZ XBMLJOH UISPVHI TPNF
FYBNQMFT 8F TUBSU CZ EFƶOJOJOH B UZQF DPOTUSVDUPS XJUI POF
BSHVNFOU
$)"15&3  '6/$503 

data WhoCares a =
ItDoesnt
| Matter a
| WhatThisIsCalled
deriving (Eq, Show)

5IJT EBUBUZQF POMZ IBT POF EBUB DPOTUSVDUPS DPOUBJOJOH B


WBMVF XF DPVME fmap PWFS BOE UIBU JT Matter 5IF PUIFST BSF
OVMMBSZ TP UIFSF JT OP WBMVF UP XPSL XJUI JOTJEF UIF TUSVDUVSF
UIFSF JT POMZ TUSVDUVSF
)FSF XF TFF B MBXBCJEJOH JOTUBODF

instance Functor WhoCares where


fmap _ ItDoesnt = ItDoesnt
fmap _ WhatThisIsCalled =
WhatThisIsCalled
fmap f (Matter a) = Matter (f a)

0VS JOTUBODF NVTU GPMMPX UIF JEFOUJUZ MBX PS FMTF JUƊT OPU B
WBMJE GVODUPS 5IBU MBX EJDUBUFT UIBU fmap id (Matter _) NVTU
OPU UPVDI Matter ƈ UIBU JT JU NVTU CF JEFOUJDBM UP id (Matter _)
'VODUPS JT B XBZ PG MJǒJOH PWFS TUSVDUVSF NBQQJOH
JO TVDI B
NBOOFS UIBU ZPV EPOƊU IBWF UP DBSF BCPVU UIF TUSVDUVSF CFDBVTF
ZPVƊSF OPU BMMPXFE UP UPVDI UIF TUSVDUVSF BOZXBZ
-FU VT OFYU DPOTJEFS B MBXCSFBLJOH JOTUBODF
$)"15&3  '6/$503 

instance Functor WhoCares where


fmap _ ItDoesnt = WhatThisIsCalled
fmap f WhatThisIsCalled = ItDoesnt
fmap f (Matter a) = Matter (f a)

/PX XF DPOUFNQMBUF XIBU JU NFBOT UP MFBWF UIF TUSVDUVSF VO


UPVDIFE *O UIJT JOTUBODF XFƊWF NBEF PVS TUSVDUVSF ƈ OPU UIF
WBMVFT XSBQQFE PS DPOUBJOFE XJUIJO UIF TUSVDUVSF ƈ DIBOHF
CZ NBLJOH ItDoesnt BOE WhatThisIsCalled EP B MJUUMF EPTFZEP
*U CFDPNFT SBQJEMZ BQQBSFOU XIZ UIJT JTOƊU LPTIFS BU BMM

Prelude> fmap id ItDoesnt


WhatThisIsCalled
Prelude> fmap id WhatThisIsCalled
ItDoesnt
Prelude> fmap id ItDoesnt == id ItDoesnt
False
Prelude> fmap id WhatThisIsCalled == id WhatThisIsCalled
False

5IJT DFSUBJOMZ EPFT OPU BCJEF CZ UIF JEFOUJUZ MBX *U JT OPU B


WBMJE 'VODUPS JOTUBODF

5IF MBX XPO #VU XIBU JG ZPV EP XBOU B GVODUJPO UIBU DBO
DIBOHF UIF WBMVF BOE UIF TUSVDUVSF
8FƊWF HPU XPOEFSGVM OFXT GPS ZPV UIBU FYJTUT *UƊT KVTU B
QMBJO PME GVODUJPO 8SJUF POF 8SJUF NBOZ 5IF QPJOU PG
$)"15&3  '6/$503 

'VODUPS JT UP SFJGZ BOE CF BCMF UP UBML BCPVU DBTFT XIFSF XF


XBOU UP SFVTF GVODUJPOT JO UIF QSFTFODF PG NPSF TUSVDUVSF
BOE CF USBOTQBSFOUMZ PCMJWJPVT UP UIBU BEEJUJPOBM TUSVDUVSF 8F
BMSFBEZ TBX UIBU 'VODUPS JT JO TPNF TFOTF KVTU B TQFDJBM TPSU PG
GVODUJPO BQQMJDBUJPO CVU TJODF JU JT TQFDJBM XF XBOU UP QSFTFSWF
UIF UIJOHT BCPVU JU UIBU NBLF JU EJƵFSFOU BOE NPSF QPXFSGVM
UIBO PSEJOBSZ GVODUJPO BQQMJDBUJPO 4P XF TUJDL UP UIF MBXT
-BUFS JO UIJT DIBQUFS XF XJMM UBML BCPVU B TPSU PG PQQPTJUF
XIFSF ZPV DBO USBOTGPSN UIF TUSVDUVSF CVU MFBWF UIF UZQF BS
HVNFOU BMPOF 5IJT IBT B OJDF TQFDJBM OBNF UPP CVU UIFSF JTOƊU
B XJEFMZ BHSFFE VQPO UZQFDMBTT

$PNQPTJUJPO TIPVME KVTU XPSL


"MM SJHIU OPX UIBU XFƊWF TFFO IPX XF DBO NBLF B 'VODUPS
JOTUBODF WJPMBUF UIF JEFOUJUZ MBX MFUƊT UBLF B MPPL BU IPX XF
BCJEF CZ ƈ BOE CSFBL ƈ UIF DPNQPTJUJPO MBX :PV NBZ SFDBMM
GSPN BCPWF UIBU UIF MBX MPPLT MJLF UIJT

fmap (f . g) == fmap f . fmap g

5FDIOJDBMMZ UIJT GPMMPXT GSPN fmap id == id CVU JUƊT XPSUI


DBMMJOH PVU TP UIBU XF DBO UBML BCPVU DPNQPTJUJPO 5IJT MBX
TBZT DPNQPTJOH UXP GVODUJPOT MJǒFE TFQBSBUFMZ TIPVME QSP
EVDF UIF TBNF SFTVMU BT JG XF DPNQPTFE UIF GVODUJPOT BIFBE
PG UJNF BOE UIFO MJǒFE UIF DPNQPTFE GVODUJPO BMM UPHFUIFS
.BJOUBJOJOH UIJT QSPQFSUZ JT BCPVU QSFTFSWJOH DPNQPTBCJMJUZ
$)"15&3  '6/$503 

PG PVS DPEF BOE QSFWFOUJOH PVS TPǒXBSF GSPN EPJOH VOQMFBT


BOUMZ TVSQSJTJOH UIJOHT 8F XJMM OPX DPOTJEFS BOPUIFS JOWBMJE
'VODUPS JOTUBODF UP TFF XIZ UIJT JT CBE OFXT

data CountingBad a =
Heisenberg Int a
deriving (Eq, Show)

-- super NOT okay


instance Functor CountingBad where
fmap f (Heisenberg n a) = Heisenberg (n+1) (f a)
-- (a -> b) f a = f b

8FMM XIBU EJE XF EP IFSF CountingBad IBT POF UZQF BSHV


NFOU CVU Heisenberg IBT UXP BSHVNFOUT *G ZPV MPPL BU IPX
UIBU MJOFT VQ XJUI UIF UZQF PG fmap ZPV HFU B IJOU PG XIZ UIJT
JTOƊU HPJOH UP XPSL PVU XFMM 8IBU QBSU PG PVS fmap UZQF EPFT
UIF ԝ SFQSFTFOUJOH UIF *OU BSHVNFOU UP )FJTFOCFSH CFMPOH UP
8F DBO MPBE UIJT IPSSJCMFOFTT VQ JO UIF 3&1- BOE TFF UIBU
DPNQPTJOH UXP fmapT IFSF EPFT OPU QSPEVDF UIF TBNF SFTVMUT
TP UIF DPNQPTJUJPO MBX EPFTOƊU IPME

Prelude> let oneWhoKnocks = Heisenberg 0 "Uncle"


Prelude> fmap (++" Jesse") oneWhoKnocks
Heisenberg 1 "Uncle Jesse"
Prelude> fmap ((++" Jesse") . (++" lol")) oneWhoKnocks
Heisenberg 1 "Uncle lol Jesse"
$)"15&3  '6/$503 

4P GBS JU TFFNT 0, CVU XIBU JG XF DPNQPTF UIF UXP DPO


DBUFOBUJPO GVODUJPOT TFQBSBUFMZ

Prelude> fmap (++ " Jesse") . fmap (++ " lol") $ oneWhoKnocks
Heisenberg 2 "Uncle lol Jesse"

0S UP NBLF JU MPPL NPSF MJLF UIF MBX

Prelude> let f = (++" Jesse")


Prelude> let g = (++" lol")
Prelude> fmap (f . g) oneWhoKnocks
Heisenberg 1 "Uncle lol Jesse"
Prelude> fmap f . fmap g $ oneWhoKnocks
Heisenberg 2 "Uncle lol Jesse"

8F DBO DMFBSMZ TFF UIBU

fmap (f . g) == fmap f . fmap g

EPFT OPU IPME 4P IPX EP XF ƶY JU

data CountingGood a =
Heisenberg Int a
deriving (Eq, Show)

-- Totes cool.
instance Functor CountingGood where
fmap f (Heisenberg n a) = Heisenberg (n) (f a)
$)"15&3  '6/$503 

+VTU TUPQ NFTTJOH XJUI UIF *OU JO )FJTFOCFSH 5IJOL PG


BOZUIJOH UIBU JTOƊU UIF ƶOBM UZQF BSHVNFOU PG PVS ԕ JO 'VODUPS
BT CFJOH QBSU PG UIF TUSVDUVSF UIBU UIF GVODUJPOT CFJOH MJǒFE
TIPVME CF PCMJWJPVT UP

 $PNNPOMZ VTFE GVODUPST


/PX UIBU XF IBWF B TFOTF PG XIBU 'VODUPS EPFT GPS VT BOE
IPX JUƊT NFBOU UP XPSL JUƊT UJNF UP TUBSU XPSLJOH UISPVHI
TPNF MPOHFS FYBNQMFT 5IJT TFDUJPO JT OFBSMZ BMM DPEF BOE
FYBNQMFT XJUI NJOJNBM QSPTF FYQMBOBUJPO *OUFSBDUJOH XJUI
UIFTF FYBNQMFT XJMM IFMQ ZPV EFWFMPQ BO JOUVJUJPO GPS XIBU BMM
JT HPJOH PO XJUI B NJOJNVN PG GVTT
8F CFHJO XJUI B TJNQMF IFMQFS GVODUJPO

Prelude> :t const
const :: a -> b -> a
Prelude> let replaceWithP = const 'p'

Prelude> replaceWithP 10000


'p'
Prelude> replaceWithP "woohoo"
'p'
Prelude> replaceWithP (Just 10)
'p'
$)"15&3  '6/$503 

8FƊMM VTF JU XJUI fmap OPX GPS WBSJPVT EBUBUZQFT UIBU IBWF
JOTUBODFT

-- data Maybe a = Nothing | Just a

Prelude> fmap replaceWithP (Just 10)


Just 'p'
Prelude> fmap replaceWithP Nothing
Nothing

-- data [] a = [] | a : [a]

Prelude> fmap replaceWithP [1, 2, 3, 4, 5]


"ppppp"
Prelude> fmap replaceWithP "Ave"
"ppp"
Prelude> fmap (+1) []
[]
Prelude> fmap replaceWithP []
""

-- data (,) a b = (,) a b

Prelude> fmap replaceWithP (10, 20)


(10,'p')
Prelude> fmap replaceWithP (10, "woo")
(10,'p')
$)"15&3  '6/$503 

"HBJO XFƊMM UBML BCPVU XIZ JU TLJQT UIF ƶSTU WBMVF JO UIF
UVQMF JO B CJU *U IBT UP EP XJUI UIF LJOEFEOFTT PG UVQMFT BOE
UIF LJOEFEOFTT PG UIF ԕ JO 'VODUPS
/PX UIF JOTUBODF GPS GVODUJPOT

Prelude> negate 10
-10
Prelude> let tossEmOne = fmap (+1) negate
Prelude> tossEmOne 10
-9
Prelude> tossEmOne (-10)
11

5IF GVODUPS PG GVODUJPOT XPOƊU CF EJTDVTTFE JO HSFBU EFUBJM


VOUJM XF HFU UP UIF DIBQUFS PO 3FBEFS CVU JU TIPVME MPPL TPSU
PG GBNJMJBS

Prelude> let tossEmOne' = (+1) . negate


Prelude> tossEmOne' 10
-9
Prelude> tossEmOne' (-10)
11

/PX ZPVƊSF TUBSUJOH UP HFU JOUP UIF HSPPWF MFUƊT TFF XIBU
FMTF XF DBO EP XJUI PVS GBODZ OFX NPWFT
$)"15&3  '6/$503 

5IF GVODUPST BSF TUBDLFE BOE UIBUƊT B GBDU


8F DBO DPNCJOF EBUBUZQFT BT XFƊWF TFFO VTVBMMZ CZ OFTUJOH
UIFN 8FƊMM CF VTJOH UIF UJMEF DIBSBDUFS BT B TIPSUIBOE GPS ƌJT
SPVHIMZ FRVJWBMFOU UPƍ UISPVHIPVU UIFTF FYBNQMFT

-- lms ~ List (Maybe (String))


Prelude> let lms = [Just "Ave", Nothing, Just "woohoo"]

Prelude> let replaceWithP = const 'p'


Prelude> replaceWithP lms
'p'

Prelude> fmap replaceWithP lms


"ppp"

/PUIJOH VOFYQFDUFE UIFSF CVU XF OPUJDF UIBU lms IBT NPSF


UIBO POF GVODUPS UZQF .BZCF BOE -JTU XIJDI JODMVEFT 4USJOH

CPUI IBWF 'VODUPS JOTUBODFT 4P BSF XF PCMJHBUFE UP fmap POMZ


UP UIF PVUFSNPTU EBUBUZQF /P XBZ NBUF

Prelude> (fmap . fmap) replaceWithP lms


[Just 'p',Nothing,Just 'p']

Prelude> (fmap . fmap . fmap) replaceWithP lms


[Just "ppp",Nothing,Just "pppppp"]

-FUƊT SFWJFX XIBU XF KVTU TBX CVU XJUI BO 9SBZ UVSOFE PO
$)"15&3  '6/$503 

-- lms ~ List (Maybe String)

Prelude> let lms = [Just "Ave", Nothing, Just "woohoo"]

Prelude> replaceWithP lms


'p'

Prelude> :t replaceWithP lms


replaceWithP lms :: Char

-- In:
replaceWithP lms

-- replaceWithP's input type is:


List (Maybe String)

-- The output type is Char

-- So applying
replaceWithP

-- to
lms

-- accomplishes
List (Maybe String) -> Char
$)"15&3  '6/$503 

5IF PVUQVU UZQF PG replaceWithP JT BMXBZT UIF TBNF


*G XF EP UIJT

Prelude> fmap replaceWithP lms


"ppp"

-- fmap is going to leave the list


-- structure intact around our result:
Prelude> :t fmap replaceWithP lms
fmap replaceWithP lms :: [Char]

)FSFƊT UIF 9SBZ WJFX

-- In:
fmap replaceWithP lms

-- replaceWithP's input type is:


Maybe String

-- The output type is Char

-- So applying
fmap replaceWithP

-- to
lms
$)"15&3  '6/$503 

-- accomplishes:
List (Maybe String) -> List Char

-- List Char ~ String

8IBU JG XF MJǒ UXJDF

,FFQ PO TUBDLJOH UIFN VQ

Prelude> (fmap . fmap) replaceWithP lms


[Just 'p',Nothing,Just 'p']

Prelude> :t (fmap . fmap) replaceWithP lms


(fmap . fmap) replaceWithP lms :: [Maybe Char]

"OE UIF 9SBZ WJFX

-- In:
(fmap . fmap) replaceWithP lms

-- replaceWithP's input type is:


-- String aka List Char or [Char]

-- The output type is Char

-- So applying
(fmap . fmap) replaceWithP
$)"15&3  '6/$503 

-- to
lms

-- accomplishes
List (Maybe String) -> List (Maybe Char)

8BJU IPX EPFT UIBU FWFO UZQFDIFDL *U NBZ OPU TFFN PCWJ
PVT BU ƶSTU IPX (fmap . fmap) DPVME UZQFDIFDL 8FƊSF HPJOH UP
BTL ZPV UP XPSL UISPVHI UIF UZQFT :PV NJHIU QSFGFS UP XSJUF
JU PVU XJUI QFO BOE QBQFS BT +VMJF EPFT PS UZQF JU BMM PVU JO B
UFYU FEJUPS BT $ISJT EPFT 8FƊMM IFMQ ZPV PVU CZ QSPWJEJOH UIF
UZQF TJHOBUVSFT 4JODF UIF UXP fmap GVODUJPOT CFJOH DPNQPTFE
DPVME IBWF EJƵFSFOU UZQFT XFƊMM NBLF UIF UZQF WBSJBCMFT GPS
FBDI GVODUJPO VOJRVF 4UBSU CZ TVCTUJUVUJOH UIF UZQF PG FBDI
fmap GPS FBDI PG UIF GVODUJPO UZQFT JO UIF (.) TJHOBUVSF

(.) :: (b -> c) -> (a -> b) -> a -> c


-- fmap fmap
fmap :: Functor f => (m -> n) -> f m -> f n
fmap :: Functor g => (x -> y) -> g x -> g y

*U NJHIU BMTP CF IFMQGVM UP RVFSZ UIF UZQF PG (fmap . fmap)


UP HFU BO JEFB PG XIBU ZPVS FOE UZQF TIPVME MPPL MJLF NPEVMP
EJƵFSFOU UZQF WBSJBCMFT

$)"15&3  '6/$503 

-Jǒ NF CBCZ POF NPSF UJNF

8F IBWF BOPUIFS MBZFS XF DBO MJǒ PWFS JG XF XJTI

Prelude> (fmap . fmap . fmap) replaceWithP lms


[Just "ppp",Nothing,Just "pppppp"]

Prelude> :t (fmap . fmap . fmap) replaceWithP lms


(fmap . fmap . fmap) replaceWithP lms :: [Maybe [Char]]

"OE UIF 9SBZ WJFX

-- In
(fmap . fmap . fmap) replaceWithP lms

-- replaceWithP's input type is:


-- Char
-- because we lifted over
-- the [] of [Char]

-- The output type is Char

-- So applying
(fmap . fmap . fmap) replaceWithP

-- to
lms
$)"15&3  '6/$503 

-- accomplishes
List (Maybe String) -> List (Maybe String)

4P XF TFF UIFSFƊT B QBUUFSO

5IF SFBM UZQF PG UIJOH HPJOH EPXO

8F TBX UIF QBUUFSO BCPWF CVU GPS DMBSJUZ XFƊSF HPJOH UP TVN
NBSJ[F IFSF CFGPSF XF NPWF PO

Prelude> fmap replaceWithP lms


"ppp"

Prelude> (fmap . fmap) replaceWithP lms


[Just 'p',Nothing,Just 'p']

Prelude> (fmap . fmap . fmap) replaceWithP lms


[Just "ppp",Nothing,Just "pppppp"]

-FUƊT TVNNBSJ[F UIF UZQFT UPP UP WBMJEBUF PVS VOEFSTUBOE


JOH
$)"15&3  '6/$503 

-- replacing the type synonym String


-- with the underlying type [Char] intentionally

replaceWithP' :: [Maybe [Char]] -> Char


replaceWithP' = replaceWithP

[Maybe [Char]] -> [Char]


[Maybe [Char]] -> [Maybe Char]
[Maybe [Char]] -> [Maybe [Char]]

1BVTF GPS B TFDPOE BOE NBLF TVSF ZPVƊSF VOEFSTUBOEJOH


FWFSZUIJOH XFƊWF EPOF TP GBS *G OPU QMBZ XJUI JU VOUJM JU TUBSUT
UP GFFM DPNGPSUBCMF

(FU PO VQ BOE HFU EPXO

8FƊMM XPSL UISPVHI UIF TBNF JEFB CVU XJUI NPSF GVOLZ TUSVD
UVSF UP MJǒ PWFS

-- lmls ~ List (Maybe (List String))

Prelude> let ha = Just ["Ha", "Ha"]


Prelude> let lmls = [ha, Nothing, Just []]

Prelude> (fmap . fmap) replaceWithP lmls


[Just 'p',Nothing,Just 'p']
$)"15&3  '6/$503 

Prelude> (fmap . fmap . fmap) replaceWithP lmls


[Just "pp",Nothing,Just ""]

Prelude> (fmap . fmap . fmap . fmap) replaceWithP lmls


[Just ["pp","pp"],Nothing,Just []]

4FF JG ZPV DBO USBDF UIF DIBOHJOH SFTVMU UZQFT BT XF EJE


BCPWF

0OF NPSF SPVOE GPS UIF 1'VOLTIVO


'PS UIPTF XIP MJLF UIFJS GVOL VODVU IFSFƊT BOPUIFS MPPL BU UIF
DIBOHJOH UZQFT UIBU SFTVMU GSPN MJǒJOH PWFS NVMUJQMF MBZFST PG
GVODUPSJBM TUSVDUVSF XJUI B TMJHIUMZ IJHIFS SFTPMVUJPO 8F TUBSU
UIJT UJNF GSPN B TPVSDF ƶMF

module ReplaceExperiment where

replaceWithP :: b -> Char


replaceWithP = const 'p'

lms :: [Maybe [Char]]


lms = [Just "Ave", Nothing, Just "woohoo"]

-- Just making the argument more specific


replaceWithP' :: [Maybe [Char]] -> Char
replaceWithP' = replaceWithP
$)"15&3  '6/$503 

8IBU IBQQFOT JG XF MJǒ JU

-- Prelude> :t fmap replaceWithP


-- fmap replaceWithP :: Functor f => f a -> f Char

liftedReplace :: Functor f => f a -> f Char


liftedReplace = fmap replaceWithP

#VU XF DBO BTTFSU B NPSF TQFDJƶD UZQF GPS liftedReplace

liftedReplace' :: [Maybe [Char]] -> [Char]


liftedReplace' = liftedReplace

5IF [] BSPVOE $IBS JT UIF ԕ PG f Char PS UIF TUSVDUVSF XF


MJǒFE PWFS 5IF ԕ PG f a JT UIF PVUFSNPTU [] JO <.BZCF <$IBS>>
4P ԕ JT JOTUBOUJBUFE UP [] XIFO XF NBLF UIF UZQF NPSF TQFDJƶD
XIFUIFS CZ BQQMZJOH JU UP B WBMVF PG UZQF [Maybe [Char]] PS CZ
NFBOT PG FYQMJDJUMZ XSJUJOH liftedReplace'

4UBZ PO UIF TDFOF MJLF BO GNBQ NBDIJOF

8IBU JG XF MJǒ JU UXJDF


$)"15&3  '6/$503 

-- Prelude> :t (fmap . fmap) replaceWithP


-- (fmap . fmap) replaceWithP
-- :: (Functor f1, Functor f) => f (f1 a) -> f (f1 Char)
twiceLifted :: (Functor f1, Functor f) =>
f (f1 a) -> f (f1 Char)
twiceLifted = (fmap . fmap) replaceWithP

-- Making it more specific


twiceLifted' :: [Maybe [Char]] -> [Maybe Char]
twiceLifted' = twiceLifted
-- f ~ []
-- f1 ~ Maybe

5ISJDF
$)"15&3  '6/$503 

-- Prelude> :t (fmap . fmap . fmap) replaceWithP


-- (fmap . fmap . fmap) replaceWithP
-- :: (Functor f2, Functor f1, Functor f) =>
-- f (f1 (f2 a)) -> f (f1 (f2 Char))
thriceLifted :: (Functor f2, Functor f1, Functor f) =>
f (f1 (f2 a)) -> f (f1 (f2 Char))
thriceLifted = (fmap . fmap . fmap) replaceWithP

-- More specific or "concrete"


thriceLifted' :: [Maybe [Char]] -> [Maybe [Char]]
thriceLifted' = thriceLifted
-- f ~ []
-- f1 ~ Maybe
-- f2 ~ []

/PX XF DBO QSJOU UIF SFTVMUT GSPN PVS FYQSFTTJPOT BOE


DPNQBSF UIFN
$)"15&3  '6/$503 

main :: IO ()
main = do
putStr "replaceWithP' lms: "
print (replaceWithP' lms)

putStr "liftedReplace lms: "


print (liftedReplace lms)

putStr "liftedReplace' lms: "


print (liftedReplace' lms)

putStr "twiceLifted lms: "


print (twiceLifted lms)

putStr "twiceLifted' lms: "


print (twiceLifted' lms)

putStr "thriceLifted lms: "


print (thriceLifted lms)

putStr "thriceLifted' lms: "


print (thriceLifted' lms)

#F TVSF UP UZQF BMM UIJT JOUP B ƶMF MPBE JU JO ()$J SVO main
UP TFF XIBU PVUQVU SFTVMUT 5IFO NPEJGZ UIF UZQFT BOE DPEF
$)"15&3  '6/$503 

CBTFE JEFBT BOE HVFTTFT PG XIBU TIPVME BOE TIPVMEOƊU XPSL


'PSNJOH IZQPUIFTFT DSFBUJOH FYQFSJNFOUT CBTFE PO UIFN
PS NPEJGZJOH FYJTUJOH FYQFSJNFOUT BOE WBMJEBUJOH UIFN JT B
DSJUJDBM QBSU PG CFDPNJOH DPNGPSUBCMF XJUI BCTUSBDUJPOT MJLF
'VODUPS

&YFSDJTFT )FBWZ -JǒJOH


"EE fmap QBSFOUIFTFT BOE GVODUJPO DPNQPTJUJPO UP UIF FYQSFT
TJPO BT OFFEFE GPS UIF FYQSFTTJPO UP UZQFDIFDL BOE QSPEVDF
UIF FYQFDUFE SFTVMU *U NBZ OPU BMXBZT OFFE UP HP JO UIF TBNF
QMBDF TP EPOƊU HFU DPNQMBDFOU

 a = (+1) $ read "[1]" :: [Int]

&YQFDUFE SFTVMU

Prelude> a
[2]

 b = (++ "lol") (Just ["Hi,", "Hello"])

Prelude> b
Just ["Hi,lol","Hellolol"]

 c = (*2) (\x -> x - 2)


$)"15&3  '6/$503 

Prelude> c 1
-2

 d = ((return '1' ++) . show) (\x -> [x, 1..3])

Prelude> d 0
"1[0,1,2,3]"

 e :: IO Integer
e = let ioi = readIO "1" :: IO Integer
changed = read ("123"++) show ioi
in (*3) changed

Prelude> e
3693

 5SBOTGPSNJOH UIF VOBQQMJFE UZQF


BSHVNFOU
8FƊWF TFFO UIBU ԕ NVTU CF B IJHIFSLJOEFE UZQF BOE UIBU 'VOD
UPS JOTUBODFT NVTU BCJEF CZ UXP MBXT BOE XFƊWF QMBZFE BSPVOE
XJUI TPNF CBTJD GNBQQJOH 8F LOPX UIBU UIF HPBM PG GNBQQJOH
JT UP MFBWF UIF PVUFS TUSVDUVSF VOUPVDIFE XIJMF USBOTGPSNJOH
UIF UZQF BSHVNFOUT JOTJEF
8BZ CBDL JO UIF CFHJOOJOH XF OPUJDFE UIBU XIFO XF fmap
PWFS B UVQMF JU POMZ USBOTGPSNT UIF TFDPOE BSHVNFOU UIF ԑ

$)"15&3  '6/$503 

8F TBX B TJNJMBS UIJOH XIFO XF GNBQQFE PWFS BO &JUIFS WBMVF


BOE XF TBJE XFƊE DPNF CBDL UP UIJT UPQJD 5IFO XF TBX BOPUIFS
IJOU PG JU BCPWF JO UIF )FJTFOCFSH FYBNQMF /PX UIF UJNF IBT
DPNF UP UBML BCPVU XIBU IBQQFOT UP UIF PUIFS UZQF BSHVNFOUT
JG BOZ
XIFO XF DBO POMZ USBOGPSN UIF JOOFSNPTU
8FƊMM TUBSU XJUI B DPVQMF PG DBOPOJDBM UZQFT

data Two a b =
Two a b
deriving (Eq, Show)

data Or a b =
First a
| Second b
deriving (Eq, Show)

:PV NBZ SFDPHOJ[F UIFTF BT (,) BOE Either SFDBQJUVMBUFE UIF


HFOFSJD QSPEVDU BOE TVN UZQFT GSPN XIJDI BOZ DPNCJOBUJPO
PG ƌBOEƍ BOE ƌPSƍ NBZ CF NBEF #VU UIFTF BSF CPUI LJOE * -> *
-> * XIJDI JTOƊU DPNQBUJCMF XJUI 'VODUPS TP IPX EP XF XSJUF
'VODUPS JOTUBODFT GPS UIFN
5IFTF XPVMEOƊU XPSL CFDBVTF Two BOE Or IBWF UIF XSPOH
LJOE
$)"15&3  '6/$503 

instance Functor Two where


fmap = undefined

instance Functor Or where


fmap = undefined

8F LOPX UIBU XF DBO QBSUJBMMZ BQQMZ GVODUJPOT BOE XFƊWF


TFFO QSFWJPVTMZ UIBU XF DBO EP UIJT

Prelude> :k Either
Either :: * -> * -> *
Prelude> :k Either Integer
Either Integer :: * -> *
Prelude> :k Either Integer String
Either Integer String :: *

5IBU IBT UIF FƵFDU PG BQQMZJOH PVU TPNF PG UIF BSHVNFOUT


SFEVDJOH UIF LJOEFEOFTT PG UIF UZQF 1SFWJPVTMZ XFƊWF EFNPO
TUSBUFE UIJT CZ BQQMZJOH UIF UZQF DPOTUSVDUPS UP DPODSFUF UZQFT
IPXFWFS ZPV DBO KVTU BT XFMM BQQMZ JU UP B UZQF WBSJBCMF UIBU
SFQSFTFOUT B UZQF DPOTUBOU UP QSPEVDF UIF TBNF FƵFDU
4P UP ƶY UIF LJOE JODPNQBUJCJMJUZ GPS PVS 5XP BOE 0S UZQFT
XF BQQMZ POF PG UIF BSHVNFOUT PG FBDI UZQF DPOTUSVDUPS HJWJOH
VT LJOE * -> *
$)"15&3  '6/$503 

-- we use 'a' for clarity, so you can see more


-- readily which type was applied out but
-- the letter doesn't matter.

instance Functor (Two a) where


fmap = undefined

instance Functor (Or a) where


fmap = undefined

5IFTF XJMM QBTT UIF UZQFDIFDLFS BMSFBEZ CVU XF TUJMM OFFE


UP XSJUF UIF JNQMFNFOUBUJPOT PG fmap GPS CPUI TP MFUƊT QSPDFFE
'JSTU XFƊMM UVSO PVS BUUFOUJPO UP 5XP

instance Functor (Two a) where


fmap f (Two a b) = Two $ (f a) (f b)

5IJT XPOƊU ƷZ FJUIFS CFDBVTF UIF Ԑ JT QBSU PG UIF GVODUPSJBM


TUSVDUVSF UIF ԕ 8FƊSF OPU TVQQPTFE UP UPVDI BOZUIJOH JO UIF
ԕ SFGFSFODFE JO UIF UZQF PG fmap TP XF DBOƊU BQQMZ UIF GVODUJPO
OBNFE ԕ JO PVS GNBQ EFƶOJUJPO
UP UIF Ԑ CFDBVTF UIF Ԑ JT OPX
VOUPVDIBCMF
$)"15&3  '6/$503 

fmap :: Functor f => (a -> b) -> f a -> f b

-- here, f is (Two a) because

class Functor f where


fmap :: (a -> b) -> f a -> f b

instance Functor (Two a) where

-- remember, names don't mean anything beyond


-- their relationships to each other.
:: (a -> b) -> (Two z) a -> (Two z) b

4P UP ƶY PVS 'VODUPS JOTUBODF XF IBWF UP MFBWF UIF MFǒ


WBMVF JUƊT QBSU PG UIF TUSVDUVSF PG ԕ
JO 5XP BMPOF BOE IBWF
PVS GVODUJPO POMZ BQQMZ UP UIF JOOFSNPTU WBMVF JO UIJT DBTF
OBNFE ԑ

instance Functor (Two a) where


fmap f (Two a b) = Two a (f b)

5IFO XJUI 0S XFƊSF EFBMJOH XJUI UIF JOEFQFOEFOU QPTTJ


CJMJUZ PG UXP EJƵFSFOU WBMVFT BOE UZQFT CVU UIF TBNF CBTJD
DPOTUSBJOU BQQMJFT
$)"15&3  '6/$503 

instance Functor (Or a) where


fmap _ (First a) = First a
fmap f (Second b) = Second (f b)

8FƊWF BQQMJFE PVU UIF ƶSTU BSHVNFOU TP OPX JUƊT QBSU PG UIF
ԕ 5IF GVODUJPO XFƊSF NBQQJOH BSPVOE UIBU TUSVDUVSF DBO POMZ
USBOTGPSN UIF JOOFSNPTU BSHVNFOU

 2VJDL$IFDLJOH 'VODUPS JOTUBODFT


8F LOPX UIF 'VODUPS MBXT BSF UIF GPMMPXJOH

fmap id = id
fmap (p . q) = (fmap p) . (fmap q)

8F DBO UVSO UIPTF JOUP UIF GPMMPXJOH 2VJDL$IFDL QSPQFS


UJFT
$)"15&3  '6/$503 

functorIdentity :: (Functor f, Eq (f a)) =>


f a
-> Bool
functorIdentity f =
fmap id f == f

functorCompose :: (Eq (f c), Functor f) =>


(a -> b)
-> (b -> c)
-> f a
-> Bool
functorCompose f g x =
(fmap g (fmap f x)) == (fmap (g . f) x)

"T MPOH BT XF QSPWJEFE DPODSFUF JOTUBODFT XF DBO OPX SVO


UIFTF UP UFTU UIFN

Prelude> quickCheck $ \x -> functorIdentity (x :: [Int])


+++ OK, passed 100 tests.

Prelude> let li x = functorCompose (+1) (*2) (x :: [Int])

Prelude> quickCheck li
+++ OK, passed 100 tests.

(SPPWZ
$)"15&3  '6/$503 

.BLJOH 2VJDL$IFDL HFOFSBUF GVODUJPOT UPP


2VJDL$IFDL IBQQFOT UP PƵFS UIF BCJMJUZ UP HFOFSBUF GVODUJPOT
5IFSFƊT B EJƵFSFOU CVU SFMBUFE UZQFDMBTT DBMMFE $P"SCJUSBSZ UIJT
DPWFST UIF GVODUJPO BSHVNFOU UZQF XIFSF "SCJUSBSZ JT VTFE GPS
UIF GVODUJPO SFTVMU UZQF *G ZPVƊSF DVSJPVT BCPVU UIJT UBLF B
MPPL BU UIF 'VODUJPO NPEVMF JO UIF 2VJDL$IFDL MJCSBSZ UP TFF
IPX GVODUJPOT BSF HFOFSBUFE GSPN B EBUBUZQF UIBU SFQSFTFOUT
QBUUFSOT JO GVODUJPO DPOTUSVDUJPO

{-# LANGUAGE ViewPatterns #-}

import Test.QuickCheck
import Test.QuickCheck.Function

functorCompose' :: (Eq (f c), Functor f) =>


f a
-> Fun a b
-> Fun b c
-> Bool
functorCompose' x (Fun _ f) (Fun _ g) =
(fmap (g . f) x) == (fmap g . fmap f $ x)

5IFSF BSF B DPVQMF UIJOHT HPJOH PO IFSF 0OF JT UIBU XF


OFFEFE UP JNQPSU B OFX NPEVMF GSPN 2VJDL$IFDL "OPUIFS
JT UIBU XFƊSF QBUUFSO NBUDIJOH PO UIF Fun WBMVF UIBU XFƊSF BTL
$)"15&3  '6/$503 

JOH 2VJDL$IFDL UP HFOFSBUF 5IF VOEFSMZJOH Fun UZQF JT FT


TFOUJBMMZ B QSPEVDU PG UIF XFJSE GVODUJPO UZQF BOE BO PSEJ
OBSZ )BTLFMM GVODUJPO HFOFSBUFE GSPN UIF XFJSEP 5IF XFJSEP
2VJDL$IFDLTQFDJƶD DPODSFUF GVODUJPO JT B GVODUJPO SFQSF
TFOUFE CZ B EBUBUZQF XIJDI DBO CF JOTQFDUFE BOE SFDVSTFE 8F
POMZ XBOU UIF TFDPOE QBSU UIF PSEJOBSZ )BTLFMM GVODUJPO TP
XFƊSF QBUUFSONBUDIJOH UIBU POF PVU

Prelude> type IntToInt = Fun Int Int


Prelude> type IntFC = [Int] -> IntToInt -> IntToInt -> Bool
Prelude> quickCheck (functorCompose' :: IntFC)
+++ OK, passed 100 tests.

/PUF PG XBSOJOH ZPV DBOƊU QSJOU UIPTF 'VO WBMVFT TP verboseCheck


XJMM DVSTF 4PDSBUFT BOE TQJO JO B DJSDMF JG ZPV USZ JU

 &YFSDJTFT *OTUBODFT PG 'VOD


*NQMFNFOU 'VODUPS JOTUBODFT GPS UIF GPMMPXJOH EBUBUZQFT 6TF
UIF 2VJDL$IFDL QSPQFSUJFT XF KVTU TIPXFE ZPV UP WBMJEBUF
UIFN

 newtype Identity a = Identity a

 data Pair a = Pair a a

 data Two a b = Two a b


$)"15&3  '6/$503 

 data Three a b c = Three a b c

 data Three' a b = Three' a b b

 data Four a b c d = Four a b c d

 data Four' a b = Four' a a a b

 $BO ZPV JNQMFNFOU POF GPS UIJT UZQF 8IZ 8IZ OPU

data Trivial = Trivial

%PJOH UIFTF FYFSDJTFT JT DSJUJDBM UP VOEFSTUBOEJOH IPX 'VOD


UPST XPSL EP OPU TLJQ QBTU UIFN

 *HOPSJOH QPTTJCJMJUJFT


8FƊWF BMSFBEZ UPVDIFE PO UIF .BZCF BOE &JUIFS GVODUPST /PX
XFƊMM FYBNJOF JO B CJU NPSF EFUBJM XIBU UIPTF EP GPS VT "T UIF
UJUMF PG UIJT TFDUJPO TVHHFTUT UIF 'VODUPS JOTUBODFT GPS UIFTF
EBUBUZQFT BSF IBOEZ GPS UJNFT ZPV JOUFOE UP JHOPSF UIF MFǒ
DBTFT XIJDI BSF UZQJDBMMZ ZPVS FSSPS PS GBJMVSF DBTFT #FDBVTF
fmap EPFTOƊU UPVDI UIPTF DBTFT ZPV DBO NBQ ZPVS GVODUJPO
SJHIU UP UIF WBMVFT UIBU ZPV JOUFOE UP XPSL XJUI BOE JHOPSF
UIPTF GBJMVSF DBTFT
$)"15&3  '6/$503 

.BZCF
-FUƊT TUBSU XJUI TPNF PSEJOBSZ QBUUFSO NBUDIJOH PO .BZCF

incIfJust :: Num a => Maybe a -> Maybe a


incIfJust (Just n) = Just $ n + 1
incIfJust Nothing = Nothing

showIfJust :: Show a => Maybe a -> Maybe String


showIfJust (Just s) = Just $ show s
showIfJust Nothing = Nothing

8FMM UIBUƊT CPSJOH BOE UIFSFƊT TPNF SFEVOEBOU TUSVDUVSF


'PS POF UIJOH UIFZ IBWF UIF /PUIJOH DBTF JO DPNNPO

someFunc Nothing = Nothing

5IFO UIFZƊSF KVTU BQQMZJOH TPNF GVODUJPO UP UIF WBMVF JG JUƊT


B +VTU

someFunc (Just x) = Just $ someOtherFunc x

8IBU IBQQFOT JG XF VTF fmap

incMaybe :: Num a => Maybe a -> Maybe a


incMaybe m = fmap (+1) m

showMaybe :: Show a => Maybe a -> Maybe String


showMaybe s = fmap show s
$)"15&3  '6/$503 

5IBU BQQFBST UP IBWF DMFBOFE UIJOHT VQ B CJU %PFT JU TUJMM


XPSL

Prelude> incMaybe (Just 1)


Just 2
Prelude> incMaybe Nothing
Nothing
Prelude> showMaybe (Just 9001)
Just "9001"
Prelude> showMaybe Nothing
Nothing

:FBI fmap IBT OP SFBTPO UP DPODFSO JUTFMG XJUI UIF /PUIJOH


ƈ UIFSFƊT OP WBMVF UIFSF GPS JU UP PQFSBUF PO TP UIJT BMM TFFNT
UP CF XPSLJOH QSPQFSMZ
#VU XF DBO BCTUSBDU UIJT B CJU NPSF 'PS POF UIJOH XF DBO
FUB DPOUSBDU UIFTF GVODUJPOT 5IBU JT XF DBO SFXSJUF UIFN
XJUIPVU OBNJOH UIF BSHVNFOUT

incMaybe'' :: Num a => Maybe a -> Maybe a


incMaybe'' = fmap (+1)

showMaybe'' :: Show a => Maybe a -> Maybe String


showMaybe'' = fmap show

"OE UIFZ EPOƊU FWFO SFBMMZ IBWF UP CF TQFDJƶD UP .BZCF


fmap XPSLT GPS BMM EBUBUZQFT XJUI B 'VODUPS JOTUBODF *O GBDU
$)"15&3  '6/$503 

XF DBO RVFSZ UIF UZQF PG UIF FYQSFTTJPOT JO ()$J BOE TFF GPS
PVSTFMWFT UIF NPSF HFOFSJD UZQF

Prelude> :t fmap (+1)


fmap (+1) :: (Functor f, Num b) => f b -> f b

Prelude> :t fmap show


fmap show :: (Functor f, Show a) => f a -> f String

8JUI UIBU XF DBO SFXSJUF UIFN BT NVDI NPSF HFOFSJD GVOD


UJPOT

-- ``lifted'' because they've been lifted over


-- some structure f

liftedInc :: (Functor f, Num b) => f b -> f b


liftedInc = fmap (+1)

liftedShow :: (Functor f, Show a) => f a -> f String


liftedShow = fmap show

"OE UIFZ IBWF UIF TBNF CFIBWJPS BT BMXBZT

Prelude> liftedInc (Just 1)


Just 2
Prelude> liftedInc Nothing
Nothing
$)"15&3  '6/$503 

Prelude> liftedShow (Just 1)


Just "1"
Prelude> liftedShow Nothing
Nothing

.BLJOH UIFN NPSF QPMZNPSQIJD JO UIF UZQF PG UIF GVODUP


SJBM TUSVDUVSF NFBOT UIFZƊSF NPSF SFVTBCMF OPX

Prelude> liftedInc [1..5]


[2,3,4,5,6]

Prelude> liftedShow [1..5]


["1","2","3","4","5"]

&YFSDJTF 1PTTJCMZ

8SJUF B 'VODUPS JOTUBODF GPS B EBUBUZQF JEFOUJDBM UP .BZCF


8FƊMM VTF PVS PXO EBUBUZQF CFDBVTF .BZCF BMSFBEZ IBT B 'VOD
UPS JOTUBODF BOE XF DBOOPU NBLF B EVQMJDBUF POF

data Possibly a =
LolNope
| Yeppers a
deriving (Eq, Show)

instance Functor Possibly where


fmap = undefined
$)"15&3  '6/$503 

*G JU IFMQT ZPVƊSF CBTJDBMMZ XSJUJOH UIF GPMMPXJOH GVODUJPO

applyIfJust :: (a -> b) -> Maybe a -> Maybe b

&JUIFS
5IF .BZCF UZQF TPMWFT B MPU PG QSPCMFNT GPS )BTLFMMFST #VU
JU EPFTOƊU TPMWF BMM PG UIFN "T XF TBX JO B QSFWJPVT DIBQUFS
TPNFUJNFT XF XBOU UP QSFTFSWF UIF SFBTPO XIZ B DPNQVUBUJPO
GBJMFE SBUIFS UIBO POMZ UIF JOGPSNBUJPO UIBU JU GBJMFE "OE GPS
UIBU XF VTF &JUIFS
#Z UIJT QPJOU ZPV LOPX UIBU &JUIFS IBT B 'VODUPS JOTUBODF
SFBEZNBEF GPS VTF CZ HSBUFGVM QSPHSBNNFST 4P MFUƊT QVU JU UP
VTF 8FƊMM TUJDL UP UIF TBNF QBUUFSO XF VTFE GPS EFNPOTUSBUJOH
.BZCF GPS UIF TBLF PG DMBSJUZ

incIfRight :: Num a => Either e a -> Either e a


incIfRight (Right n) = Right $ n + 1
incIfRight (Left e) = Left e

showIfRight :: Show a => Either e a -> Either e String


showIfRight (Right s) = Right $ show s
showIfRight (Left e) = Left e

0ODF BHBJO XF DBO TJNQMJGZ UIFTF VTJOH fmap TP XF EPOƊU


IBWF UP BEESFTT UIF PCWJPVT ƌMFBWF UIF FSSPS WBMVF BMPOFƍ DBTF
$)"15&3  '6/$503 

incEither :: Num a => Either e a -> Either e a


incEither m = fmap (+1) m

showEither :: Show a => Either e a -> Either e String


showEither s = fmap show s

"OE BHBJO XF DBO FUB DPOUSBDU UP ESPQ UIF PCWJPVT BSHV


NFOU

incEither' :: Num a => Either e a -> Either e a


incEither' = fmap (+1)

showEither' :: Show a => Either e a -> Either e String


showEither' = fmap show

"OE PODF BHBJO XF BSF DPOGSPOUFE XJUI GVODUJPOT UIBU SFBMMZ


EJEOƊU OFFE UP CF TQFDJƶD UP &JUIFS BU BMM

-- f ~ Either e

liftedInc :: (Functor f, Num b) => f b -> f b


liftedInc = fmap (+1)

liftedShow :: (Functor f, Show a) => f a -> f String


liftedShow = fmap show
$)"15&3  '6/$503 

5BLF B GFX NPNFOUT UP QMBZ BSPVOE XJUI UIJT BOE OPUF IPX
JU XPSLT

4IPSU &YFSDJTF

 8SJUF B 'VODUPS JOTUBODF GPS B EBUBUZQF JEFOUJDBM UP &JUIFS


8FƊMM VTF PVS PXO EBUBUZQF CFDBVTF &JUIFS BMTP BMSFBEZ
IBT B 'VODUPS JOTUBODF

data Sum a b =
First a
| Second b
deriving (Eq, Show)

instance Functor (Sum a) where


fmap = undefined

:PVS IJOU GPS UIJT POF JT UIBU ZPVƊSF XSJUJOH UIF GPMMPXJOH
GVODUJPO

applyIfSecond :: (a -> b) -> (Sum e) a -> (Sum e) b

 8IZ JT B 'VODUPS JOTUBODF UIBU BQQMJFT UIF GVODUJPO POMZ


UP First &JUIFSƊT -Fǒ JNQPTTJCMF 8F DPWFSFE UIJT FBSMJFS
$)"15&3  '6/$503 

 " TPNFXIBU TVSQSJTJOH GVODUPS


5IFSFƊT B EBUBUZQF OBNFE Const PS Constant ZPVƊMM TFF CPUI
OBNFT EFQFOEJOH PO XIJDI MJCSBSZ ZPV VTF Constant IBT B
WBMJE Functor CVU UIF CFIBWJPS PG UIF 'VODUPS JOTUBODF NBZ
TVSQSJTF ZPV B CJU 'JSTU MFUƊT MPPL BU UIF const GVODUJPO BOE
UIFO XFƊMM MPPL BU UIF EBUBUZQF

Prelude> :t const
const :: a -> b -> a
Prelude> let a = const 1
Prelude> a 1
1
Prelude> a 2
1
Prelude> a 3
1
Prelude> a "blah"
1
Prelude> a id
1

8JUI B TJNJMBS DPODFQU JO NJOE UIFSF JT UIF $POTUBOU EBUBUZQF


$POTUBOU MPPLT MJLF UIJT
$)"15&3  '6/$503 

newtype Constant a b =
Constant { getConstant :: a }
deriving (Eq, Show)

0OF UIJOH XF OPUJDF BCPVU UIJT UZQF JT UIBU UIF UZQF QBSBN
FUFS ԑ JT B QIBOUPN UZQF *U IBT OP DPSSFTQPOEJOH XJUOFTT BU
UIF WBMVFUFSN MFWFM 5IJT JT B DPODFQU BOE UBDUJD XFƊMM FYQMPSF
NPSF MBUFS CVU GPS OPX XF DBO TFF IPX JU FDIPFT UIF GVODUJPO
const

Prelude> Constant 2
Constant {getConstant = 2}

%FTQJUF ԑ CFJOH B QIBOUPN UZQF UIPVHI $POTUBOU JT LJOE *


-> * -> * BOE UIBU JT OPU B WBMJE 'VODUPS 4P IPX EP XF HFU POF
8FMM UIFSFƊT POMZ POF UIJOH XF DBO EP XJUI B UZQF DPOTUSVDUPS
KVTU BT XJUI GVODUJPOT BQQMZ JU 4P XF EP IBWF B 'VODUPS GPS
Constant a KVTU OPU $POTUBOU BMPOF *U IBT UP CF Constant a BOE
OPU Constant a b CFDBVTF Constant a b XPVME CF LJOE *
-FUƊT MPPL BU UIF JNQMFNFOUBUJPO PG 'VODUPS GPS $POTUBOU

instance Functor (Constant m) where


fmap _ (Constant v) = Constant v

-PPLT MJLF JEFOUJUZ SJHIU -FUƊT VTF UIJT JO UIF 3&1- BOE SVO
JU UISPVHI UIF 'VODUPS MBXT
$)"15&3  '6/$503 

Prelude> const 2 (getConstant (Constant 3))


2
Prelude> fmap (const 2) (Constant 3)
Constant {getConstant = 3}

Prelude> getConstant $ fmap (const 2) (Constant 3)


3
Prelude> getConstant $ fmap (const "blah") (Constant 3)
3

8IFO ZPV fmap UIF const GVODUJPO PWFS UIF $POTUBOU UZQF
UIF ƶSTU BSHVNFOU UP const JT OFWFS VTFE CFDBVTF UIF QBSUJBMMZ
BQQMJFE const JT JUTFMG OFWFS VTFE 5IF ƶSTU UZQF BSHVNFOU UP
ConstantƊT UZQF DPOTUSVDUPS JT JO UIF QBSU PG UIF TUSVDUVSF UIBU
'VODUPS TLJQT PWFS 5IF TFDPOE BSHVNFOU UP UIF Constant UZQF
DPOTUSVDUPS JT UIF QIBOUPN UZQF WBSJBCMF ԑ XIJDI IBT OP WBMVF
PS UFSNMFWFM XJUOFTT JO UIF EBUBUZQF 4JODF UIFSF BSF OP WBMVFT
PG UIF UZQF UIF 'VODUPS JT TVQQPTFE UP CF NBQQJOH XF IBWF
OPUIJOH XFƊSF BMMPXFE UP BQQMZ UIF fmapƊE GVODUJPO UP TP XF
OFWFS VTF UIF const FYQSFTTJPOT
#VU EPFT UIJT BEIFSF UP UIF 'VODUPS MBXT

-- Testing identity
Prelude> getConstant (id (Constant 3))
3
Prelude> getConstant (fmap id (Constant 3))
$)"15&3  '6/$503 

-- Composition of the const function


Prelude> ((const 3) . (const 5)) 10
3
Prelude> ((const 5) . (const 3)) 10
5

-- Composition
Prelude> let separate = fmap (const 3) . fmap (const 5)
Prelude> let fused = fmap ((const 3) . (const 5))
Prelude> getConstant $ separate $ (Constant "WOOHOO")
"WOOHOO"
Prelude> getConstant $ fused $ (Constant "Dogs rule")
"Dogs rule"

(Constant a) JT * -> * XIJDI ZPV OFFE GPS UIF 'VODUPS CVU


OPX ZPVƊSF NBQQJOH PWFS UIBU ԑ BOE OPU UIF Ԑ
5IJT JT B NFSF DVSTPSZ DIFDL OPU B QSPPG UIBU UIJT JT B WBMJE
'VODUPS .PTU BTTVSBODFT PG DPSSFDUOFTT UIBU QSPHSBNNFST VTF
FYJTU PO B HSBEJFOU BOE BSFOƊU QSPQFS QSPPGT %FTQJUF TFFNJOH
B CJU QPJOUMFTT Constant JT B MBXGVM 'VODUPS
$)"15&3  '6/$503 

 .PSF TUSVDUVSF NPSF GVODUPST


data Wrap f a =
Wrap (f a)
deriving (Eq, Show)

/PUJDF UIBU PVS Ԑ IFSF JT BO BSHVNFOU UP UIF ԕ 4P IPX BSF


XF HPJOH UP XSJUF B GVODUPS JOTUBODF GPS UIJT

instance Functor (Wrap f) where


fmap f (Wrap fa) = Wrap (f fa)

instance Functor (Wrap f) where


fmap f (Wrap fa) = Wrap (fmap f fa)

instance Functor f => Functor (Wrap f) where


fmap f (Wrap fa) = Wrap (fmap f fa)

"OE JG XF MPBE VQ UIF ƶOBM JOTUBODF XIJDI TIPVME XPSL XF


DBO VTF UIJT XSBQQFS UZQF

Prelude> fmap (+1) (Wrap (Just 1))


Wrap (Just 2)

Prelude> fmap (+1) (Wrap [1, 2, 3])


Wrap [2,3,4]
$)"15&3  '6/$503 

*U TIPVME XPSL GPS BOZ 'VODUPS *G XF QBTT JU TPNFUIJOH UIBU


JTOƊU

Prelude> let n = 1 :: Integer


Prelude> fmap (+1) (Wrap n)

Couldn't match expected type ‘f b’ with actual type ‘Integer’


Relevant bindings include
it :: Wrap f b (bound at <interactive>:8:1)
In the first argument of ‘Wrap’, namely ‘n’
In the second argument of ‘fmap’, namely ‘(Wrap n)’

5IF OVNCFS CZ JUTFMG EPFTOƊU PƵFS UIF BEEJUJPOBM TUSVDUVSF


OFFET GPS 8SBQ UP XPSL BT B 'VODUPS *UƊT FYQFDUJOH UP CF BCMF
UP GNBQ PWFS TPNF ԕ JOEFQFOEFOU PG BO Ԑ BOE UIJT KVTU JTOƊU UIF
DBTF XJUI BOZ UZQF DPOTUBOU TVDI BT *OUFHFS

 *0 'VODUPS
8FƊWF TFFO UIF IO UZQF JO UIF NPEVMFT BOE UFTUJOH DIBQUFST
BMSFBEZ CVU XF XFSFOƊU EPJOH NVDI XJUI JU TBWF UP QSJOU UFYU
PS BTL GPS TUSJOH JOQVU GSPN UIF VTFS 5IF IO UZQF XJMM HFU
B GVMM DIBQUFS PG JUT PXO MBUFS JO UIF CPPL *U JT BO BCTUSBDU
EBUBUZQF UIFSF BSF OP EBUB DPOTUSVDUPST UIBU ZPVƊSF QFSNJUUFE
UP QBUUFSO NBUDI PO TP UIF UZQFDMBTTFT IO QSPWJEFT BSF UIF
$)"15&3  '6/$503 

POMZ XBZ ZPV DBO XPSL XJUI WBMVFT PG UZQF IO a 0OF PG UIF
TJNQMFTU QSPWJEFE JT 'VODUPS

-- getLine :: IO String
-- read :: Read a => String -> a

getInt :: IO Int
getInt = fmap read getLine

*OU IBT B 3FBE JOTUBODF BOE fmap MJǒT read PWFS UIF IO UZQF "
XBZ ZPV DBO SFBE getLine IFSF JT UIBU JUƊT OPU B 4USJOH CVU SBUIFS
B XBZ UP PCUBJO B TUSJOH IO EPFTOƊU HVBSBOUFF UIBU FƵFDUT XJMM
CF QFSGPSNFE CVU JU EPFT NFBO UIBU UIFZ DPVME CF QFSGPSNFE
)FSF UIF TJEF FƵFDU JT OFFEJOH UP CMPDL BOE XBJU GPS VTFS JOQVU
WJB UIF TUBOEBSE JOQVU TUSFBN UIF 04 QSPWJEFT

Prelude> getInt
10
10

8F FOUFS  BOE IJU FOUFS ()$J QSJOUT IO WBMVFT VOMFTT UIF


UZQF JT IO () JO XIJDI DBTF JU IJEFT UIF Unit WBMVF CFDBVTF JUƊT
NFBOJOHMFTT

Prelude> fmap (const ()) getInt


10
$)"15&3  '6/$503 

5IF ƌƍ JO UIF ()$J TFTTJPO BCPWF JT NZ FOUFSJOH  BOE


IJUUJOH FOUFS ()$J JTOƊU QSJOUJOH BOZ SFTVMU BǒFS UIBU CFDBVTF
XFƊSF SFQMBDJOH UIF *OU WBMVF XF SFBE GSPN B 4USJOH 5IBU
JOGPSNBUJPO JT HFUUJOH ESPQQFE PO UIF ƷPPS CFDBVTF XF BQQMJFE
const () UP UIF DPOUFOUT PG UIF IO Int *G XF JHOPSF UIF QSFTFODF
PG *0 JUƊT BT JG XF EJE UIJT

Prelude> let getInt = 10 :: Int


Prelude> const () getInt
()

()$J BT B NBUUFS PG DPOWFOJFODF BOE EFTJHO XJMM OPU QSJOU


BOZ WBMVF PG UZQF IO () PO UIF BTTVNQUJPO UIBU UIF *0 BDUJPO
ZPV FWBMVBUFE XBT FWBMVBUFE GPS FƵFDUT BOE CFDBVTF UIF VOJU
WBMVF DBOOPU DPNNVOJDBUF BOZUIJOH 8F DBO VTF UIF SFUVSO
GVODUJPO TFFO FBSMJFS FYQMBJOFE MBUFS
UP ƌQVUƍ B VOJU WBMVF JO
*0 BOE SFQSPEVDF UIJT CFIBWJPS PG ()$JƊT

Prelude> return 1 :: IO Int


1
Prelude> ()
()
Prelude> return () :: IO ()
Prelude>

8IBU JG XF XBOU UP EP TPNFUIJOH NPSF VTFGVM 8F DBO fmap


BOZ GVODUJPO XF XBOU PWFS IO
$)"15&3  '6/$503 

Prelude> fmap (+1) getInt


10
11

Prelude> fmap (++ " and me too!") getLine


hello
"hello and me too!"

8F DBO BMTP VTF do TZOUBY UP EP XIBU XFƊSF EPJOH XJUI 'VOD


UPS IFSF

meTooIsm :: IO String
meTooIsm = do
input <- getLine
return (input ++ "and me too!")

bumpIt :: IO Int
bumpIt = do
intVal <- getInt
return (intVal + 1)

#VU JG fmap f TVƸDFT GPS XIBU ZPVƊSF EPJOH UIBUƊT VTVBMMZ


TIPSUFS BOE DMFBSFS *UƊT QFSGFDUMZ BMM SJHIU BOE RVJUF DPNNPO
UP TUBSU XJUI B NPSF WFSCPTF GPSN PG TPNF FYQSFTTJPO BOE
UIFO DMFBO JU VQ BǒFS ZPVƊWF HPU TPNFUIJOH UIBU XPSLT
$)"15&3  '6/$503 

 8IBU JG XF XBOU UP EP TPNFUIJOH


EJƵFSFOU
8F UBMLFE BCPVU 'VODUPS BT B NFBOT PG MJǒJOH GVODUJPOT PWFS
TUSVDUVSF TP UIBU XF NBZ USBOTGPSN POMZ UIF DPOUFOUT MFBWJOH
UIF TUSVDUVSF BMPOF 8IBU JG XF XBOUFE UP USBOTGPSN POMZ UIF
TUSVDUVSF BOE MFBWF UIF UZQF BSHVNFOU UP UIBU TUSVDUVSF PS UZQF
DPOTUSVDUPS BMPOF 8JUI UIJT XFƊWF BSSJWFE BU OBUVSBM USBOTGPS
NBUJPOT 8F DBO BUUFNQU UP QVU UPHFUIFS B UZQF UP FYQSFTT XIBU
XF XBOU

nat :: (f -> g) -> f a -> g a

5IJT UZQF JT JNQPTTJCMF CFDBVTF XF DBOƊU IBWF IJHIFSLJOEFE


UZQFT BT BSHVNFOU UZQFT UP UIF GVODUJPO UZQF 8IBUƊT UIF
QSPCMFN UIPVHI *U MPPLT MJLF UIF UZQF TJHOBUVSF GPS fmap
EPFTOƊU JU :FU ԕ BOE Ԗ JO f -> g BSF IJHIFSLJOEFE UZQFT 5IFZ
NVTU CF CFDBVTF UIFZ BSF UIF TBNF ԕ BOE Ԗ UIBU MBUFS JO UIF
UZQF TJHOBUVSF BSF UBLJOH BSHVNFOUT #VU JO UIPTF QMBDFT UIFZ
BSF BQQMJFE UP UIFJS BSHVNFOUT BOE TP IBWF LJOE *
4P XF NBLF B NPEFTU DIBOHF UP ƶY JU

{-# LANGUAGE RankNTypes #-}

type Nat f g = forall a. f a -> g a


$)"15&3  '6/$503 

4P JO B TFOTF XFƊSF EPJOH UIF PQQPTJUF PG XIBU B 'VODUPS


EPFT 8FƊSF USBOTGPSNJOH UIF TUSVDUVSF QSFTFSWJOH UIF WBMVFT
BT UIFZ XFSF 8F XPOƊU FYQMBJO JU GVMMZ IFSF CVU UIF RVBOUJƶ
DBUJPO PG Ԑ JO UIF SJHIUIBOE TJEF PG UIF EFDMBSBUJPO BMMPXT VT
UP PCMJHBUF BMM GVODUJPOT PG UIJT UZQF UP CF PCMJWJPVT UP UIF DPO
UFOUT PG UIF TUSVDUVSFT ԕ BOE Ԗ JO NVDI UIF TBNF XBZ UIBU UIF
JEFOUJUZ GVODUJPO DBOOPU EP BOZUIJOH CVU SFUVSO UIF BSHVNFOU
JU XBT HJWFO
4ZOUBDUJDBMMZ JU MFUT VT BWPJE UBMLJOH BCPVU Ԑ JO UIF UZQF PG
/BU ƈ XIJDI JT XIBU XF XBOU XF TIPVMEOƊU IBWF BOZ TQFDJƶD
JOGPSNBUJPO BCPVU UIF DPOUFOUT PG ԕ BOE Ԗ CFDBVTF XFƊSF TVQ
QPTFE UP CF POMZ QFSGPSNJOH B TUSVDUVSBM USBOTGPSNBUJPO OPU
B GPME
*G ZPV USZ UP FMJEF UIF Ԑ GSPN UIF UZQF BSHVNFOUT XJUIPVU
RVBOUJGZJOH JU TFQBSBUFMZ ZPVƊMM HFU BO FSSPS

Prelude> type Nat f g = f a -> g a

Not in scope: type variable ‘a’

8F DBO BEE UIF RVBOUJƶFS CVU JG XF GPSHFU UP UVSO PO 3BOL5ZQFT


PS 3BOL/5ZQFT JU XPOƊU XPSL

Prelude> type Nat f g = forall a . f a -> g a

Illegal symbol '.' in type


Perhaps you intended to use RankNTypes or a
$)"15&3  '6/$503 

similar language extension to enable


explicit-forall syntax: forall <tvs>. <type>

*G XF UVSO PO 3BOL5ZQFT PS 3BOL/5ZQFT JU XPSLT ƶOF

Prelude> :set -XRank2Types


Prelude> type Nat f g = forall a . f a -> g a
Prelude>

5P TFF BO FYBNQMF PG XIBU UIF RVBOUJƶDBUJPO QSFWFOUT DPO


TJEFS UIF GPMMPXJOH

type Nat f g = forall a . f a -> g a

-- This'll work
maybeToList :: Nat Maybe []
maybeToList Nothing = []
maybeToList (Just a) = [a]

-- This will not work, not allowed.


degenerateMtl :: Nat Maybe []
degenerateMtl Nothing = []
degenerateMtl (Just a) = [a+1]

8IBU JG XF VTF B WFSTJPO PG /BU UIBU NFOUJPOT Ԑ JO UIF UZQF


$)"15&3  '6/$503 

module BadNat where

type Nat f g a = f a -> g a

-- This'll work
maybeToList :: Nat Maybe [] a
maybeToList Nothing = []
maybeToList (Just a) = [a]

-- But this will too if we tell it


-- 'a' is Num a => a

degenerateMtl :: Num a => Nat Maybe [] a


degenerateMtl Nothing = []
degenerateMtl (Just a) = [a+1]

5IBU MBTU FYBNQMF TIPVME OPU XPSL BOE JT OPU B HPPE XBZ UP
UIJOL BCPVU OBUVSBM USBOTGPSNBUJPO 1BSU PG TPǒXBSF JT CFJOH
QSFDJTF BOE XIFO XF UBML BCPVU OBUVSBM USBOTGPSNBUJPOT XFƊSF
TBZJOH BT NVDI BCPVU XIBU XF EPOƊU XBOU BT XF BSF BCPVU XIBU
XF EP XBOU *O UIJT DBTF UIF JOWBSJBOU XF XBOU UP QSFTFSWF JT
UIBU UIF GVODUJPO DBOOPU EP BOZUIJOH NJTDIJFWPVT XJUI UIF
WBMVFT *G ZPV XBOU TPNFUIJOH DMFWFS KVTU XSJUF B QMBJO PME
GPME
8FƊSF HPJOH UP SFUVSO UP UIF UPQJD PG OBUVSBM USBOTGPSNBUJPOT
$)"15&3  '6/$503 

JO UIF OFYU DIBQUFS TP DPPM ZPVS KFUT GPS OPX

 'VODUPST BSF VOJRVF UP B EBUBUZQF


*O )BTLFMM 'VODUPS JOTUBODFT XJMM CF VOJRVF GPS B HJWFO EBUBUZQF
8F TBX UIBU UIJT JTOƊU USVF GPS .POPJE IPXFWFS XF VTF OFX
UZQFT UP BWPJE DPOGVTJOH EJƵFSFOU .POPJE JOTUBODFT GPS B HJWFO
UZQF #VU 'VODUPS JOTUBODFT XJMM CF VOJRVF GPS B EBUBUZQF JO
QBSU CFDBVTF PG QBSBNFUSJDJUZ JO QBSU CFDBVTF BSHVNFOUT UP
UZQF DPOTUSVDUPST BSF BQQMJFE JO PSEFS PG EFƶOJUJPO *O B IZQP
UIFUJDBM OPU)BTLFMM MBOHVBHF UIF GPMMPXJOH NJHIU CF QPTTJCMF

data Tuple a b =
Tuple a b
deriving (Eq, Show)

-- this is impossible in Haskell


instance Functor (Tuple ? b) where
fmap f (Tuple a b) = Tuple (f a) b

5IFSF BSF FTTFOUJBMMZ UXP XBZT UP BEESFTT UIJT 0OF JT UP ƷJQ


UIF BSHVNFOUT UP UIF UZQF DPOTUSVDUPS UIF PUIFS JT UP NBLF B
OFX EBUBUZQF VTJOH B Flip OFXUZQF
$)"15&3  '6/$503 

{-# LANGUAGE FlexibleInstances #-}

module FlipFunctor where

data Tuple a b =
Tuple a b
deriving (Eq, Show)

newtype Flip f a b =
Flip (f b a)
deriving (Eq, Show)

-- this actually works, goofy as it looks.


instance Functor (Flip Tuple a) where
fmap f (Flip (Tuple a b)) = Flip $ Tuple (f a) b

Prelude> fmap (+1) (Flip (Tuple 1 "blah"))


Flip (Tuple 2 "blah")

)PXFWFS Flip Tuple a b JT B EJTUJODU UZQF GSPN Tuple a b


FWFO JG JUƊT POMZ UIFSF UP QSPWJEF GPS EJƵFSFOU 'VODUPS JOTUBODF
CFIBWJPS
$)"15&3  '6/$503 

 $IBQUFS FYFSDJTFT


%FUFSNJOF JG B WBMJE 'VODUPS DBO CF XSJUUFO GPS UIF EBUBUZQF
QSPWJEFE

 data Bool =
False | True

 data BoolAndSomethingElse a =
False' a | True' a

 data BoolAndMaybeSomethingElse a =
Falsish | Truish a

 6TF UIF LJOET UP HVJEF ZPV PO UIJT POF EPOƊU HFU UPP IVOH
VQ PO UIF EFUBJMT

newtype Mu f = InF { outF :: f (Mu f) }

 "HBJO KVTU GPMMPX UIF LJOET BOE JHOPSF UIF VOGBNJMJBS


QBSUT

import GHC.Arr

data D =
D (Array Word Word) Int Int

3FBSSBOHF UIF BSHVNFOUT UP UIF UZQF DPOTUSVDUPS PG UIF


EBUBUZQF TP UIF 'VODUPS JOTUBODF XPSLT
$)"15&3  '6/$503 

 data Sum a b =
First a
| Second b

instance Functor (Sum e) where


fmap f (First a) = First (f a)
fmap f (Second b) = Second b

 data Company a b c =
DeepBlue a c
| Something b

instance Functor (Company e e') where


fmap f (Something b) = Something (f b)
fmap _ (DeepBlue a c) = DeepBlue a c

 data More a b =
L a b a
| R b a b
deriving (Eq, Show)

instance Functor (More x) where


fmap f (L a b a') = L (f a) b (f a')
fmap f (R b a b') = R b (f a) b'
$)"15&3  '6/$503 

,FFQJOH JO NJOE UIBU JU TIPVME SFTVMU JO B 'VODUPS UIBU


EPFT UIF GPMMPXJOH

Prelude> fmap (+1) (L 1 2 3)


L 2 2 4
Prelude> fmap (+1) (R 1 2 3)
R 1 3 3

8SJUF 'VODUPS JOTUBODFT GPS UIF GPMMPXJOH EBUBUZQFT

 data Quant a b =
Finance
| Desk a
| Bloor b

 /P JUƊT OPU JOUFSFTUJOH CZ JUTFMG

data K a b =
K a
$)"15&3  '6/$503 

 {-# LANGUAGE FlexibleInstances #-}

newtype Flip f a b =
Flip (f b a)
deriving (Eq, Show)

newtype K a b =
K a

-- should remind you of an


-- instance you've written before
instance Functor (Flip K a) where
fmap = undefined

 data EvilGoateeConst a b =
GoatyConst b

-- You thought you'd escaped the goats


-- by now didn't you? Nope.

/P JU EPFTOƊU EP BOZUIJOH JOUFSFTUJOH /P NBHJD IFSF PS


JO UIF QSFWJPVT FYFSDJTF *G JU XPSLT ZPV TVDDFFEFE

 %P ZPV OFFE TPNFUIJOH FYUSB UP NBLF UIF JOTUBODF XPSL

data LiftItOut f a =
LiftItOut (f a)
$)"15&3  '6/$503 

 data Parappa f g a =
DaWrappa (f a) (g a)

 %POƊU BTL GPS NPSF UZQFDMBTT JOTUBODFT UIBO ZPV OFFE :PV
DBO MFU ()$ UFMM ZPV XIBU UP EP

data IgnoreOne f g a b =
IgnoringSomething (f a) (g b)

 data Notorious g o a t =
Notorious (g o) (g a) (g t)

 :PVƊMM OFFE UP VTF SFDVSTJPO

data List a =
Nil
| Cons a (List a)

 " USFF PG HPBUT GPSNT B (PBU-PSE GFBSTPNF QPMZDSFBUVSF

data GoatLord a =
NoGoat
| OneGoat a
| MoreGoats (GoatLord a) (GoatLord a) (GoatLord a)

-- A VERITABLE HYDRA OF GOATS

 :PVƊMM VTF BO FYUSB GVODUPS GPS UIJT POF BMUIPVHI ZPVS TPMV
UJPO NJHIU EP JU NPOPNPSQIJDBMMZ XJUIPVU VTJOH GNBQ
$)"15&3  '6/$503 

,FFQ JO NJOE UIBU ZPV XJMM QSPCBCMZ OPU CF BCMF UP WBMJ


EBUF UIJT POF JO UIF VTVBM NBOOFS %P ZPVS CFTU UP NBLF
JU XPSL

data TalkToMe a =
Halt
| Print String a
| Read (String -> a)

 %FƶOJUJPOT
 )JHIFSLJOEFE QPMZNPSQIJTN JT QPMZNPSQIJTN XIJDI IBT
B UZQF WBSJBCMF BCTUSBDUJOH PWFS UZQFT PG B IJHIFS LJOE
'VODUPS JT BO FYBNQMF PG IJHIFS LJOEFE QPMZNPSQIJTN
CFDBVTF UIF LJOE PG UIF G QBSBNFUFS UP 'VODUPS JT * -> *
"OPUIFS FYBNQMF PG IJHIFS LJOEFE QPMZNPSQIJTN XPVME
CF B EBUBUZQF IBWJOH B QBSBNFUFS UP UIF UZQF DPOTUSVDUPS
XIJDI JT PG B IJHIFS LJOE TVDI BT UIF GPMMPXJOH

data Weird f a = Weird (f a)

8IFSF UIF LJOET PG UIF UZQFT JOWPMWFE BSF

a :: *
f :: * -> *
Weird :: (* -> *) -> * -> *

5IBOLT UP "OESB[ #BKU GPS JOTQJSJOH UIJT FYFSDJTF
$)"15&3  '6/$503 

)FSF CPUI 8FJSE BOE G BSF IJHIFS LJOEFE XJUI 8FJSE


CFJOH BO FYBNQMF PG IJHIFS LJOEFE QPMZNPSQIJTN

 'VODUPS JT B NBQQJOH CFUXFFO DBUFHPSJFT *O )BTLFMM UIJT


NBOJGFTUT BT B UZQFDMBTT XIJDI MJǒT B GVODUJPO CFUXFFO
UXP UZQFT PWFS UXP OFX UZQFT 5IJT DPOWFOUJPOBMMZ JN
QMJFT TPNF OPUJPO PG B GVODUJPO XIJDI DBO CF BQQMJFE UP B
WBMVF XJUI NPSF TUSVDUVSF UIBO UIF VOMJǒFE GVODUJPO XBT
PSJHJOBMMZ EFTJHOFE GPS 5IF BEEJUJPOBM TUSVDUVSF JT SFQSF
TFOUFE CZ UIF VTF PG B IJHIFS LJOEFE UZQF ԕ JOUSPEVDFE
CZ UIF EFƶOJUJPO PG UIF 'VODUPS UZQFDMBTT

f :: a -> b

-- ``more structure''
fmap f :: f a -> f b

-- f is applied to a single argument,


-- and so is kind * -> *

0OF TIPVME CF DBSFGVM OPU UP DPOGVTF UIJT JOUVJUJPO GPS


JU OFDFTTBSJMZ CFJOH FYDMVTJWFMZ BCPVU DPOUBJOFST PS EBUB
TUSVDUVSFT 5IFSFƊT B 'VODUPS PG GVODUJPOT BOE NBOZ FY
PUJD UZQFT XJMM IBWF B MBXGVM 'VODUPS JOTUBODF

 -FUƊT UBML BCPVU MJǕJOH #FDBVTF NPTU PG UIF SFTU PG UIF CPPL
EFBMT XJUI BQQMJDBUJWFT BOE NPOBET PG WBSJPVT ƷBWPST
$)"15&3  '6/$503 

XFƊSF HPJOH UP CF MJǒJOH B MPU CVU XIBU EP XF NFBO *O


UIJT CPPL XF NPTU DPNNPOMZ VTF UIF QISBTF MJǕ PWFS
MBUFS JO .POBE CJOE PWFS GPS SFBTPOT UIBU XJMM IPQFGVMMZ
CFDPNF DMFBS JO UJNF
CVU JUƊT JNQPSUBOU UP VOEFSTUBOE
UIBU UIJT JT B NFUBQIPS BOE TQBUJBM NFUBQIPST DBO BU
UJNFT PCTDVSF BT NVDI BT UIFZ DMBSJGZ 8IFO $BSOBQ ƶSTU
EFTDSJCFE GVODUPST JO UIF DPOUFYU PG MJOHVJTUJDT IF EJEOƊU
SFBMMZ UBML BCPVU JU BT MJǒJOH BOZUIJOH BOE NBUIFNBUJDJBOT
IBWF GPMMPXFE JO IJT GPPUTUFQT GPDVTJOH PO NBQQJOH BOE
UIF QSPEVDUJPO PG PVUQVUT GSPN DFSUBJO UZQFT PG JOQVUT
7FSZ NBUIFNBUJDBM PG UIFN BOE ZFU )BTLFMMFST VTF UIF
MJǒJOH NFUBQIPS PǒFO BT XF EP JO UIJT CPPL

5IFSF BSF B DPVQMF PG XBZT UP UIJOL BCPVU JU 0OF JT UIBU
XF DBO MJǒ B GVODUJPO JOUP B DPOUFYU "OPUIFS JT UIBU XF MJǒ
B GVODUJPO PWFS TPNF MBZFS PG TUSVDUVSF UP BQQMZ JU 5IF
FƵFDU JT UIF TBNF

Prelude> fmap (+1) $ Just 1


Just 2
Prelude> fmap (+1) [1, 2, 3]
[2,3,4]

*O CPUI DBTFT UIF GVODUJPO XFƊSF MJǒJOH JT UIF TBNF *O


UIF ƶSTU DBTF XF MJǒ UIBU GVODUJPO JOUP B .BZCF DPOUFYU JO
PSEFS UP BQQMZ JU JO UIF TFDPOE DBTF JOUP B MJTU DPOUFYU *U
$)"15&3  '6/$503 

DBO CF IFMQGVM UP UIJOL PG JU JO UFSNT PG MJǒJOH UIF GVOD


UJPO JOUP UIF DPOUFYU CFDBVTF JUƊT UIF DPOUFYU XFƊWF MJǒFE
UIF GVODUJPO JOUP UIBU EFUFSNJOFT IPX UIF GVODUJPO XJMM
HFU BQQMJFE UP KVTU POF WBMVF PS SFDVSTJWFMZ UP NBOZ GPS
FYBNQMF
 5IF DPOUFYU JT UIF EBUBUZQF UIF EFƶOJUJPO PG
UIF EBUBUZQF BOE UIF 'VODUPS JOTUBODF XF IBWF GPS UIBU
EBUBUZQF *UƊT BMTP UIF DPOUFYUT UIBU EFUFSNJOF XIBU IBQ
QFOT XIFO XF USZ UP BQQMZ B GVODUJPO UP BO Ԑ UIBU JTOƊU
UIFSF

Prelude> fmap (+1) []


[]
Prelude> fmap (+1) Nothing
Nothing

#VU XF PǒFO TQFBL NPSF DBTVBMMZ BCPVU MJǒJOH PWFS BT JO


fmap MJǒT B GVODUJPO PWFS B EBUB DPOTUSVDUPS 5IJT XPSLT
UPP JG ZPV UIJOL PG UIF EBUB DPOTUSVDUPS BT B MBZFS PG TUSVD
UVSF 5IF GVODUJPO IPQT PWFS UIBU MBZFS BOE BQQMJFT UP
XIBUƊT JOTJEF JG BOZUIJOH
:PV NJHIU ƶOE POF PS UIF PUIFS XBZ PG UBMLJOH BCPVU MJǒJOH
NPSF PS MFTT IFMQGVM EFQFOEJOH PO UIF DPOUFYU 5SZ UP
LFFQ JO NJOE UIBU JUƊT B NFUBQIPS OPU B QSFDJTF EFƶOJUJPO
BOE GPMMPX UIF UZQFT SBUIFS UIBO HFUUJOH UPP DBVHIU VQ JO
UIF NFUBQIPS
$)"15&3  '6/$503 

 (FPSHF $MJOUPO JT POF PG UIF NPTU JNQPSUBOU JOOPWBUPST PG


GVOL NVTJD $MJOUPO IFBEFE VQ UIF CBOET 1BSMJBNFOU BOE
'VOLBEFMJD XIPTF DPMMFDUJWF TUZMF PG NVTJD JT LOPXO BT
1'VOL UIF UXP CBOET IBWF GVTFE JOUP B TJOHMF BQPUIFPTJT
PG CPPUZTIBLJOH SIZUIN 5IF 1BSMJBNFOU BMCVN .PUIFS
TIJQ $POOFDUJPO JT POF PG UIF NPTU GBNPVT BOE JOƷVFOUJBM
BMCVNT JO SPDL IJTUPSZ /PU B 'VODUPS CVU ZPV DBO QSF
UFOE UIF BMCVN JT NBQQJOH ZPVS DPOTDJPVTOFTT GSPN UIF
SFBM XPSME JOUP UIF DBUFHPSZ PG GVOLJOFTT JG UIBU IFMQT

 'PMMPXVQ SFTPVSDFT


 )BTLFMM 8JLJCPPL 5IF 'VODUPS DMBTT
https://en.wikibooks.org/wiki/Haskell/The_Functor_class

 .BSL 1 +POFT " TZTUFN PG DPOTUSVDUPS DMBTTFT PWFSMPBE


JOH BOE JNQMJDJU IJHIFSPSEFS QPMZNPSQIJTN

 (BCSJFM (PO[BMF[ 5IF GVODUPS EFTJHO QBUUFSO


$IBQUFS 

"QQMJDBUJWF

ƒUIF JNBHFT * NPTU


DPOOFDU UP IJTUPSJDBMMZ
TQFBLJOH BSF JO CMBDL BOE
XIJUF * TFF NPSF JO CMBDL
BOE XIJUF Ƈ * MJLF UIF
BCTUSBDUJPO PG JU

.BSZ &MMFO .BSL


$)"15&3  "11-*$"5*7& 

 "QQMJDBUJWF
*O UIF QSFWJPVT DIBQUFST XFƊWF TFFO UXP DPNNPO BMHFCSBT UIBU
BSF VTFE BT UZQFDMBTTFT JO )BTLFMM .POPJE HJWFT VT B NFBOT PG
NBTIJOH UXP WBMVFT PG UIF TBNF UZQF UPHFUIFS 'VODUPS PO UIF
PUIFS IBOE JT GPS GVODUJPO BQQMJDBUJPO PWFS TPNF TUSVDUVSF XF
EPOƊU XBOU UP IBWF UP UIJOL BCPVU .POPJEƊT DPSF PQFSBUJPO
mappend TNBTIFT UIF TUSVDUVSFT UPHFUIFS ƈ XIFO ZPV mappend
UXP MJTUT UIFZ CFDPNF POF MJTU TP UIF TUSVDUVSFT UIFNTFMWFT
IBWF CFFO KPJOFE )PXFWFS UIF DPSF PQFSBUJPO PG 'VODUPS
fmap BQQMJFT B GVODUJPO UP B WBMVF UIBU JT XJUIJO TPNF TUSVDUVSF
XIJMF MFBWJOH UIBU TUSVDUVSF VOBMUFSFE
8F DPNF OPX UP "QQMJDBUJWF "QQMJDBUJWF JT B NPOPJEBM
GVODUPS /P OP TUBZ XJUI VT 5IF Applicative UZQFDMBTT BMMPXT
GPS GVODUJPO BQQMJDBUJPO MJǒFE PWFS TUSVDUVSF MJLF 'VODUPS
 #VU
XJUI "QQMJDBUJWF UIF GVODUJPO XFƊSF BQQMZJOH JT BMTP FNCFEEFE
JO TPNF TUSVDUVSF #FDBVTF UIF GVODUJPO BOE UIF WBMVF JUƊT
CFJOH BQQMJFE UP CPUI IBWF TUSVDUVSF XF IBWF UP TNBTI UIPTF
TUSVDUVSFT UPHFUIFS 4P "QQMJDBUJWF JOWPMWFT NPOPJET BOE
GVODUPST "OE UIBUƊT B QSFUUZ QPXFSGVM UIJOH
*O UIJT DIBQUFS XF XJMM

Ƒ EFƶOF BOE FYQMPSF UIF "QQMJDBUJWF UZQFDMBTT BOE JUT DPSF


PQFSBUJPOT

Ƒ EFNPOTUSBUF XIZ BQQMJDBUJWFT BSF NPOPJEBM GVODUPST


$)"15&3  "11-*$"5*7& 

Ƒ NBLF UIF VTVBM DIJUDIBU BCPVU MBXT BOE JOTUBODFT

Ƒ EP B MPU PG MJǒJOH

Ƒ HJWF ZPV TPNF 7BMJEBUJPO

 %FƶOJOH "QQMJDBUJWF


5IF ƶSTU UIJOH ZPVƊSF HPJOH UP OPUJDF BCPVU UIJT UZQFDMBTT EFD
MBSBUJPO JT UIBU UIF ԕ UIBU SFQSFTFOUT UIF TUSVDUVSF TJNJMBS UP
'VODUPS JT JUTFMG DPOTUSBJOFE CZ UIF 'VODUPS UZQFDMBTT

class Functor f => Applicative f where


pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b

4P FWFSZ UZQF UIBU DBO IBWF BO "QQMJDBUJWF JOTUBODF NVTU


BMTP IBWF B 'VODUPS JOTUBODF
5IF pure GVODUJPO EPFT B TJNQMF BOE WFSZ CPSJOH UIJOH JU
FNCFET TPNFUIJOH JOUP GVODUPSJBM BQQMJDBUJWF
TUSVDUVSF :PV
DBO UIJOL PG UIJT BT CFJOH B CBSF NJOJNVN CJU PG TUSVDUVSF PS
TUSVDUVSBM JEFOUJUZ *EFOUJUZ GPS XIBU ZPVƊMM TFF MBUFS XIFO XF
HP PWFS UIF MBXT 5IF NPSF DPSF PQFSBUJPO PG UIJT UZQFDMBTT
JT <*> 5IJT JT BO JOƶY GVODUJPO DBMMFE ƉBQQMZƊ PS TPNFUJNFT
ƉBQ Ɗ PS TPNFUJNFT ƉUJFƶHIUFSƊ XIFO XFƊSF GFFMJOH QBSUJDVMBSMZ
[JQQZ
*G XF DPNQBSF UIF UZQFT PG <*> BOE fmap XF TFF UIF TJNJMBS
JUZ
$)"15&3  "11-*$"5*7& 

-- fmap
(<$>) :: Functor f => (a -> b) -> f a -> f b

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

5IF EJƵFSFODF JT UIF ԕ SFQSFTFOUJOH GVODUPSJBM TUSVDUVSF


UIBU JT PO UIF PVUTJEF PG PVS GVODUJPO JO UIF TFDPOE EFƶOJUJPO
8FƊMM TFF HPPE FYBNQMFT PG XIBU UIBU NFBOT JO QSBDUJDF JO KVTU
B NPNFOU
"MPOH XJUI UIFTF DPSF GVODUJPOT UIF $POUSPM"QQMJDBUJWF MJ
CSBSZ QSPWJEFT TPNF PUIFS DPOWFOJFOU GVODUJPOT liftA liftA2
BOE liftA3
$)"15&3  "11-*$"5*7& 

liftA :: Applicative f =>


(a -> b)
-> f a
-> f b

liftA2 :: Applicative f =>


(a -> b -> c)
-> f a
-> f b
-> f c

liftA3 :: Applicative f =>


(a -> b -> c -> d)
-> f a
-> f b
-> f c
-> f d

*G ZPVƊSF MPPLJOH BU UIF UZQF PG liftA BOE UIJOLJOH CVU UIBUƊT


KVTU fmap ZPV BSF DPSSFDU *U JT CBTJDBMMZ UIF TBNF BT fmap POMZ
XJUI BO "QQMJDBUJWF UZQFDMBTT DPOTUSBJOU JOTUFBE PG B 'VODUPS
POF 4JODF BMM "QQMJDBUJWF JOTUBODFT BSF BMTP GVODUPST UIPVHI
UIJT JT B EJTUJODUJPO XJUIPVU NVDI TJHOJƶDBODF
4JNJMBSMZ ZPV DBO TFF UIBU liftA2 BOE liftA3 BSF KVTU fmap CVU
XJUI GVODUJPOT JOWPMWJOH NPSF BSHVNFOUT *U DBO CF B MJUUMF
$)"15&3  "11-*$"5*7& 

EJƸDVMU UP XSBQ POFƊT IFBE BSPVOE IPX UIPTF XJMM XPSL JO


QSBDUJDF TP XFƊMM XBOU UP MPPL OFYU BU TPNF TJNQMF FYBNQMFT
UP TUBSU EFWFMPQJOH B TFOTF PG XIBU BQQMJDBUJWFT DBO EP GPS VT

 'VODUPS WT "QQMJDBUJWF


8FƊWF BMSFBEZ TBJE UIBU BQQMJDBUJWFT BSF NPOPJEBM GVODUPST
TP XIBU XFƊWF BMSFBEZ MFBSOFE BCPVU .POPJE BOE 'VODUPS JT
SFMFWBOU UP PVS VOEFSTUBOEJOH PG "QQMJDBUJWF 8FƊWF BMSFBEZ
TFFO TPNF FYBNQMFT PG XIBU UIJT NFBOT JO QSBDUJDF CVU XF
XBOU UP EFWFMPQ B TUSPOHFS JOUVJUJPO GPS UIF SFMBUJPOTIJQ
-FUƊT SFWJFX UIF EJƵFSFODF CFUXFFO fmap BOE <*>

fmap :: (a -> b) -> f a -> f b


(<*>) :: f (a -> b) -> f a -> f b

5IF EJƵFSFODF BQQFBST UP CF RVJUF TNBMM BOE JOOPDVPVT


8F OPX IBWF BO ԕ JO GSPOU PG PVS GVODUJPO (a -> b) #VU UIF
JODSFBTF JO QPXFS JU JOUSPEVDFT JT QSPGPVOE 'PS POF UIJOH BOZ
"QQMJDBUJWF BMTP IBT B 'VODUPS BOE OPU NFSFMZ CZ EFƶOJUJPO ƈ
ZPV DBO EFƶOF B 'VODUPS JO UFSNT PG B QSPWJEFE "QQMJDBUJWF
JOTUBODF 1SPWJOH JU JT PVUTJEF UIF TDPQF PG UIF DVSSFOU CPPL
CVU UIJT GPMMPXT GSPN UIF MBXT PG 'VODUPS BOE "QQMJDBUJWF XFƊMM
HFU UP UIF BQQMJDBUJWF MBXT MBUFS JO UIJT DIBQUFS


fmap f x = pure f <*> x


$)"15&3  "11-*$"5*7& 

)PX NJHIU XF EFNPOTUSBUF UIJT :PVƊMM OFFE UP JNQPSU


$POUSPM"QQMJDBUJWF JG ZPVƊSF VTJOH ()$  PS PMEFS UP UFTU
UIJT FYBNQMF

Prelude> fmap (+1) [1, 2, 3]


[2,3,4]

Prelude> pure (+1) <*> [1..3]


[2,3,4]

,FFQJOH JO NJOE UIBU QVSF IBT UZQF Applicative f => a -> f


a XF DBO UIJOL PG JU BT B NFBOT PG FNCFEEJOH B WBMVF PG BOZ
UZQF JO UIF TUSVDUVSF XFƊSF XPSLJOH XJUI

Prelude> pure 1 :: [Int]


[1]
Prelude> pure 1 :: Maybe Int
Just 1
Prelude> pure 1 :: Either a Int
Right 1
Prelude> pure 1 :: ([a], Int)
([],1)

5IF MFǒ UZQF JT IBOEMFE EJƵFSFOUMZ GSPN UIF SJHIU JO UIF


ƶOBM UXP FYBNQMFT GPS UIF TBNF SFBTPO BT IFSF

Prelude> fmap (+1) (4, 5)


(4,6)
$)"15&3  "11-*$"5*7& 

5IF MFǒ UZQF JT QBSU PG UIF TUSVDUVSF BOE UIF TUSVDUVSF JT


OPU USBOTGPSNFE CZ UIF GVODUJPO BQQMJDBUJPO

 "QQMJDBUJWF GVODUPST BSF NPOPJEBM


GVODUPST
'JSTU MFU VT OPUJDF TPNFUIJOH

($) :: (a -> b) -> a -> b


(<$>) :: (a -> b) -> f a -> f b
(<*>) :: f (a -> b) -> f a -> f b

8F BMSFBEZ LOPX $ UP CF TPNFUIJOH PG B EPOPUIJOH JOƶY


GVODUJPO XIJDI FYJTUT NFSFMZ UP HJWF UIF SJHIUIBOE TJEF NPSF
QSFDFEFODF BOE UIVT BWPJE QBSFOUIFTFT 'PS PVS QSFTFOU QVS
QPTFT JU BDUT BT B OJDF QSPYZ GPS PSEJOBSZ GVODUJPO BQQMJDBUJPO
JO JUT UZQF
8IFO XF HFU UP <$> UIF BMJBT GPS fmap XF OPUJDF UIF ƶSTU
DIBOHF JT UIBU XFƊSF OPX MJǒJOH PVS (a -> b) PWFS UIF f XSBQQFE
BSPVOE PVS WBMVF BOE BQQMZJOH UIF GVODUJPO UP UIBU WBMVF
5IFO BT XF BSSJWF BU ap PS <*> UIF "QQMJDBUJWF BQQMZ NFUIPE
PVS GVODUJPO JT OPX BMTP FNCFEEFE JO UIF GVODUPSJBM TUSVDUVSF
/PX XF HFU UP UIF NPOPJEBM JO ƌNPOPJEBM GVODUPSƍ
$)"15&3  "11-*$"5*7& 

:: f (a -> b) -> f a -> f b

-- The two arguments to our function are:

f (a -> b)
-- and
f a

*G XF JNBHJOF UIBU XF DBO KVTU BQQMZ (a -> b) UP Ԑ BOE HFU ԑ


JHOPSJOH UIF GVODUPSJBM TUSVDUVSF XF TUJMM IBWF B QSPCMFN BT
XF OFFE UP SFUVSO f b 8IFO XF XFSF EFBMJOH XJUI fmap XF
IBE POMZ POF CJU PG TUSVDUVSF TP JU XBT MFǒ VODIBOHFE /PX
XF IBWF UXP CJUT PG TUSVDUVSF PG UZQF ԕ UIBU XF OFFE UP EFBM
XJUI TPNFIPX CFGPSF SFUVSOJOH B WBMVF PG UZQF f b 8F DBOƊU
TJNQMZ MFBWF UIFN VODIBOHFE XF NVTU VOJUF UIFN TPNFIPX
/PX UIFZ XJMM CF EFƶOJUFMZ UIF TBNF UZQF CFDBVTF UIF ԕ NVTU
CF UIF TBNF UZQF UISPVHIPVU *O GBDU JG XF KVTU TFQBSBUF UIF
TUSVDUVSF QBSUT GSPN UIF GVODUJPO QBSUT NBZCF XFƊMM TFF XIBU XF
OFFE

:: f (a -> b) -> f a -> f b

f f f
(a -> b) a b

%JEOƊU XF IBWF TPNFUIJOH FBSMJFS UIBU DBO UBLF UXP WBMVFT


PG POF UZQF BOE SFUVSO POF WBMVF PG UIF TBNF UZQF 1SPWJEFE
$)"15&3  "11-*$"5*7& 

UIF ԕ JT B UZQF XJUI B .POPJE JOTUBODF UIFO XF IBWF B HPPE


XBZ UP NBLF UIFN QMBZ OJDF UPHFUIFS

mappend :: Monoid a => a -> a -> a

4P XJUI "QQMJDBUJWF XF IBWF B .POPJE GPS PVS TUSVDUVSF


BOE GVODUJPO BQQMJDBUJPO GPS PVS WBMVFT

mappend :: f f f
$ :: (a -> b) a b

(<*>) :: f (a -> b) -> f a -> f b

-- plus Functor fmap to be able to map


-- over the f to begin with.

4P JO B TFOTF XFƊSF CPMUJOH B .POPJE POUP B 'VODUPS UP CF


BCMF UP EFBM XJUI GVODUJPOT FNCFEEFE JO BEEJUJPOBM TUSVDUVSF
*O BOPUIFS TFOTF XFƊSF FOSJDIJOH GVODUJPO BQQMJDBUJPO XJUI UIF
WFSZ TUSVDUVSF XF XFSF QSFWJPVTMZ NFSFMZ NBQQJOH PWFS XJUI
'VODUPS -FUƊT DPOTJEFS B GFX GBNJMJBS FYBNQMFT UP FYBNJOF
XIBU UIJT NFBOT
$)"15&3  "11-*$"5*7& 

-- List
[(*2), (*3)] <*> [4, 5]

[2 * 4, 2 * 5, 3 * 4, 3 * 5]

-- reduced

[8,10,12,15]

4P XIBU XBT (a -> b) FOSJDIFE XJUI JO f (a -> b) -> f a ->


f b *O UIJT DBTF ƌMJTUOFTTƍ "MUIPVHI UIF BDUVBM BQQMJDBUJPO
PG FBDI (a -> b) UP B WBMVF PG UZQF Ԑ JT RVJUF PSEJOBSZ XF OPX
IBWF B MJTU PG GVODUJPOT SBUIFS UIBO B TJOHMF GVODUJPO BT XPVME
CF UIF DBTF JG JU XBT KVTU UIF -JTU 'VODUPS
#VU ƌMJTUOFTTƍ JTOƊU UIF POMZ TUSVDUVSF XF DBO FOSJDI PVS
GVODUJPOT XJUI ƈ OPU FWFO DMPTF 5IJOLJOH PG 'VODUPS BOE
"QQMJDBUJWF BT UIJOHT ZPV NPTUMZ EP XJUI MJTUT JT BO FBTZ NJTUBLF
UP NBLF BT ZPVƊSF MFBSOJOH #VU UIF TUSVDUVSF CJU DBO BMTP CF
.BZCF
$)"15&3  "11-*$"5*7& 

Just (*2) <*> Just 2


=
Just 4

Just (*2) <*> Nothing


=
Nothing

Nothing <*> Just 2


=
Nothing

Nothing <*> Nothing


=
Nothing

8JUI .BZCF UIF PSEJOBSZ GVODUPS JT NBQQJOH PWFS UIF


QPTTJCJMJUZ PG B WBMVFƊT OPOFYJTUFODF 8JUI UIF "QQMJDBUJWF
OPX UIF GVODUJPO BMTP NJHIU OPU CF QSPWJEFE 8FƊMM TFF B
DPVQMF PG OJDF MPOH FYBNQMFT PG IPX UIJT NJHIU IBQQFO ƈ
IPX ZPV DPVME FOE VQ OPU FWFO QSPWJEJOH B GVODUJPO UP BQQMZ
ƈ JO KVTU B CJU OPU KVTU XJUI .BZCF CVU XJUI &JUIFS BOE B OFX
UZQF DBMMFE 7BMJEBUJPO BT XFMM
$)"15&3  "11-*$"5*7& 

4IPX NF UIF NPOPJET


3FDBMM UIBU UIF 'VODUPS JOTUBODF GPS UIF UXPUVQMF JHOPSFT UIF
ƶSTU WBMVF JOTJEF UIF UVQMF

Prelude> fmap (+1) ("blah", 0)


("blah",1)

#VU UIF "QQMJDBUJWF GPS UIF UXPUVQMF EFNPOTUSBUFT UIF


NPOPJE JO "QQMJDBUJWF OJDFMZ GPS VT *O GBDU JG ZPV DBMM :info
PO (,) JO ZPVS 3&1- ZPVƊMM OPUJDF TPNFUIJOH

Prelude> :info (,)


data (,) a b = (,) a b -- Defined in ‘GHC.Tuple’
...
instance Monoid a => Applicative ((,) a) -- Defined in ‘GHC.Base’
...
instance (Monoid a, Monoid b) => Monoid (a, b)

'PS UIF "QQMJDBUJWF JOTUBODF PG UXPUVQMF XF EPOƊU OFFE


B .POPJE GPS UIF ԑ CFDBVTF XFƊSF VTJOH GVODUJPO BQQMJDBUJPO
UP QSPEVDF UIF ԑ )PXFWFS GPS UIF ƶSTU WBMVF JO UIF UVQMF XF
TUJMM OFFE UIF .POPJE CFDBVTF XF IBWF UXP WBMVFT BOE OFFE UP
TPNFIPX UVSO UIBU JOUP POF WBMVF PG UIF TBNF UZQF

Prelude> ("Woo", (+1)) <*> (" Hoo!", 0)


("Woo Hoo!", 1)
$)"15&3  "11-*$"5*7& 

/PUJDF UIBU GPS UIF Ԑ WBMVF XF EJEOƊU BQQMZ BOZ GVODUJPO


CVU UIFZ IBWF DPNCJOFE UIFNTFMWFT BT JG CZ NBHJD UIBUƊT EVF
UP UIF .POPJE JOTUBODF GPS UIF Ԑ WBMVFT 5IF GVODUJPO JO UIF ԑ
QPTJUJPO PG UIF MFǒ UVQMF IBT CFFO BQQMJFE UP UIF WBMVF JO UIF ԑ
QPTJUJPO PG UIF SJHIU UVQMF UP QSPEVDF B SFTVMU 5IBU GVODUJPO
BQQMJDBUJPO JT XIZ XF EPOƊU OFFE B .POPJE JOTUBODF PO UIF ԑ
-FUƊT MPPL BU NPSF TVDI FYBNQMFT 1BZ DBSFGVM BUUFOUJPO UP
IPX UIF Ԑ WBMVFT JO UIF UVQMFT BSF DPNCJOFE

Prelude> import Data.Monoid


Prelude> ((Sum 2), (+1)) <*> ((Sum 0), 0)
(Sum {getSum = 2},1)

Prelude> ((Product 3), (+9)) <*> ((Product 2), 8)


(Product {getProduct = 6},17)

Prelude> ((All True), (+1)) <*> ((All False), 0)


(All {getAll = False},1)

*U EPFTOƊU SFBMMZ NBUUFS XIBU .POPJE XF KVTU OFFE TPNF


XBZ PG DPNCJOJOH PS DIPPTJOH PVS WBMVFT

5VQMF .POPJE BOE "QQMJDBUJWF TJEF CZ TJEF


4RVJOU JG ZPV DBOƊU TFF JU
$)"15&3  "11-*$"5*7& 

instance (Monoid a, Monoid b) => Monoid (a,b) where


mempty = (mempty, mempty)
(a, b) `mappend` (a',b') =
(a `mappend` a', b `mappend` b')

instance Monoid a => Applicative ((,) a) where


pure x = (mempty, x)
(u, f) <*> (v, x) =
(u `mappend` v, f x)

.BZCF .POPJE BOE "QQMJDBUJWF


8IJMF BQQMJDBUJWFT BSF SFBMMZ NPOPJEBM GVODUPST CF DBSFGVM
BCPVU UBLJOH JU UPP MJUFSBMMZ 'PS POF UIJOH .POPJE BOE "Q
QMJDBUJWF JOTUBODFT BSFOƊU SFRVJSFE PS HVBSBOUFFE UP IBWF UIF
TBNF NPOPJE PG TUSVDUVSF BOE UIF GVODUPSJBM QBSU NBZ BDUV
BMMZ DIBOHF UIJOHT /FWFSUIFMFTT ZPV NJHIU CF BCMF UP TFF UIF
JNQMJDJU NPOPJE JO IPX UIF "QQMJDBUJWF QBUUFSO NBUDIFT PO
UIF +VTU BOE /PUIJOH DBTFT BOE DPNQBSF UIBU XJUI UIJT .POPJE
$)"15&3  "11-*$"5*7& 

instance Monoid a => Monoid (Maybe a) where


mempty = Nothing
mappend m Nothing = m
mappend Nothing m = m
mappend (Just a) (Just a') = Just (mappend a a')

instance Applicative Maybe where


pure = Just

Nothing <*> _ = Nothing


_ <*> Nothing = Nothing
Just f <*> Just a = Just (f a)

*O UIF OFYU DIBQUFS XFƊSF HPJOH UP TFF TPNF FYBNQMFT PG


IPX EJƵFSFOU NPOPJE JOTUBODFT DBO HJWF EJƵFSFOU SFTVMUT GPS
BQQMJDBUJWFT 'PS OPX SFDPHOJ[F UIBU UIF NPOPJEBM CJU NBZ
OPU CF XIBU ZPV SFDPHOJ[F BT UIF DBOPOJDBM mappend PG UIBU UZQF
CFDBVTF TPNF UZQFT DBO IBWF NVMUJQMF NPOPJET

 "QQMJDBUJWF JO VTF


#Z OPX JU TIPVME DPNF BT OP TVSQSJTF UIBU NBOZ PG UIF EBUBUZQFT
XFƊWF CFFO XPSLJOH XJUI JO UIF QBTU UXP DIBQUFST BMTP IBWF
Applicative JOTUBODFT 4JODF XF BSF BMSFBEZ TP GBNJMJBS XJUI MJTU
BOE .BZCF UIPTF FYBNQMFT XJMM CF B HPPE QMBDF UP TUBSU -BUFS
$)"15&3  "11-*$"5*7& 

JO UIF DIBQUFS XF XJMM CF JOUSPEVDJOH TPNF OFX UZQFT TP KVTU


IBOH POUP ZPVS IBUT

-JTU "QQMJDBUJWF
8FƊMM TUBSU XJUI UIF MJTU BQQMJDBUJWF CFDBVTF JUƊT B DMFBS XBZ UP
HFU B TFOTF PG UIF QBUUFSO -FUƊT TUBSU CZ TQFDJBMJ[JOH UIF UZQFT

-- f ~ []

(<*>) :: f (a -> b) -> f a -> f b


(<*>) :: [ ] (a -> b) -> [ ] a -> [ ] b

-- more syntactically typical


(<*>) :: [(a -> b)] -> [a] -> [b]

pure :: a -> f a
pure :: a -> [ ] a

8IBUƊT UIF -JTU BQQMJDBUJWF EP


1SFWJPVTMZ XJUI -JTU GVODUPS XF XFSF NBQQJOH B TJOHMF GVOD
UJPO PWFS B QMVSBMJUZ PG WBMVFT

Prelude> fmap (2^) [1, 2, 3]


[2,4,8]
Prelude> fmap (^2) [1, 2, 3]
$)"15&3  "11-*$"5*7& 

[1,4,9]

8JUI UIF -JTU "QQMJDBUJWF XF BSF NBQQJOH B QMVSBMJUZ PG


GVODUJPOT PWFS B QMVSBMJUZ PG WBMVFT

Prelude> [(+1), (*2)] <*> [2, 4]


[3,5,4,8]

8F DBO TFF IPX UIJT NBLFT TFOTF HJWFO UIBU

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

f ~ []

listApply :: [(a -> b)] -> [a] -> [b]

listFmap :: (a -> b) -> [a] -> [b]

5IF ԕ TUSVDUVSF UIBU JT XSBQQFE BSPVOE PVS GVODUJPO JO UIF


listApply GVODUJPO JT JUTFMG B MJTU 5IFSFGPSF PVS a -> b GSPN
'VODUPS IBT CFDPNF B MJTU PG a -> b
/PX XIBU IBQQFOFE XJUI UIBU FYQSFTTJPO XF KVTU UFTUFE
4PNFUIJOH MJLF UIJT

[(+1), (*2)] <*> [2, 4] == [3,5,4,8]

[ 3 , 5 , 4 , 8 ]
-- [1] [2] [3] [4]
$)"15&3  "11-*$"5*7& 

 5IF ƶSTU JUFN JO UIF MJTU  JT UIF SFTVMU PG 


CFJOH BQQMJFE
UP 

  JT UIF SFTVMU PG BQQMZJOH 


UP 

  JT UIF SFTVMU PG BQQMZJOH 


UP 

  JT UIF SFTVMU PG BQQMZJOH 


UP 

.PSF WJTVBMMZ

[(+1), (*2)] <*> [2, 4]

[ (+1) 2 , (+1) 4 , (*2) 2 , (*2) 4 ]

*U NBQT FBDI GVODUJPO WBMVF GSPN UIF ƶSTU MJTU PWFS UIF TFD
POE MJTU BQQMJFT UIF PQFSBUJPOT BOE SFUVSOT POF MJTU 5IF GBDU
UIBU JU EPFTOƊU SFUVSO UXP MJTUT PS B OFTUFE MJTU PS TPNF PUIFS
DPOƶHVSBUJPO JO XIJDI CPUI TUSVDUVSFT BSF QSFTFSWFE JT UIF
NPOPJEBM QBSU UIF SFBTPO XF EPOƊU IBWF B MJTU PG GVODUJPOT
NFSFMZ DPODBUFOBUFE XJUI B MJTU PG WBMVFT JT UIF GVODUJPO BQQMJ
DBUJPO QBSU
8F DBO TFF UIJT SFMBUJPOTIJQ NPSF SFBEJMZ JG XF VTF UIF
UVQMF DPOTUSVDUPS XJUI UIF -JTU "QQMJDBUJWF 8FƊMM VTF UIF JOƶY
PQFSBUPS GPS fmap UP NBQ UIF UVQMF DPOTUSVDUPS PWFS UIF ƶSTU MJTU
5IJT FNCFET BO VOBQQMJFE GVODUJPO UIF UVQMF EBUB DPOTUSVDUPS
JO UIJT DBTF
JOUP TPNF TUSVDUVSF B MJTU JO UIJT DBTF
BOE SFUVSOT
B MJTU PG QBSUJBMMZ BQQMJFE GVODUJPOT 5IF JOƶY
BQQMJDBUJWF XJMM
$)"15&3  "11-*$"5*7& 

UIFO BQQMZ POF MJTU PG PQFSBUJPOT UP UIF TFDPOE MJTU NPOPJEBMMZ


BQQFOEJOH UIF UXP MJTUT

Prelude> (,) <$> [1, 2] <*> [3, 4]


[(1,3),(1,4),(2,3),(2,4)]

:PV NJHIU UIJOL PG JU UIJT XBZ

Prelude> (,) <$> [1, 2] <*> [3, 4]

-- first we fmap the (,) over the first list


[(1, ), (2, )] <*> [3, 4]

-- then we apply the first list


-- to the second
[(1,3),(1,4),(2,3),(2,4)]

5IF liftA2 GVODUJPO HJWFT VT BOPUIFS XBZ UP XSJUF UIJT UPP

Prelude> liftA2 (,) [1, 2] [3, 4]


[(1,3),(1,4),(2,3),(2,4)]

-FUƊT MPPL BU B GFX NPSF FYBNQMFT PG UIF TBNF QBUUFSO

Prelude> (+) <$> [1, 2] <*> [3, 5]


[4,6,5,7]
Prelude> liftA2 (+) [1, 2] [3, 5]
[4,6,5,7]
$)"15&3  "11-*$"5*7& 

Prelude> max <$> [1, 2] <*> [1, 4]


[1,4,2,4]
Prelude> liftA2 max [1, 2] [1, 4]
[1,4,2,4]

*G ZPVƊSF GBNJMJBS XJUI $BSUFTJBO QSPEVDUT UIJT QSPCBCMZ


MPPLT B MPU MJLF POF CVU XJUI GVODUJPOT
8FƊSF HPJOH UP SVO UISPVHI TPNF NPSF FYBNQMFT UP HJWF
ZPV B MJUUMF NPSF DPOUFYU GPS XIFO UIFTF GVODUJPOT DBO CFDPNF
VTFGVM 5IF GPMMPXJOH FYBNQMFT XJMM VTF B GVODUJPO DBMMFE lookup
UIBU XFƊMM CSJFƷZ EFNPOTUSBUF

Prelude> :t lookup
lookup :: Eq a => a -> [(a, b)] -> Maybe b
Prelude> lookup 3 [(3, "hello")]
Just "hello"
Prelude> fmap length $ lookup 3 [(3, "hello")]
Just 5
Prelude> let c (x:xs) = toUpper x:xs
Prelude> fmap c $ lookup 3 [(3, "hello")]
Just "Hello"

4P lookup TFBSDIFT JOTJEF B MJTU PG UVQMFT GPS B WBMVF UIBU


NBUDIFT UIF JOQVU BOE SFUVSOT UIF QBJSFE WBMVF XSBQQFE JOTJEF
B .BZCF DPOUFYU

en.wikipedia.org/wiki/Cartesian_product
$)"15&3  "11-*$"5*7& 

*UƊT XPSUI QPJOUJOH PVU IFSF UIBU JG ZPVƊSF XPSLJOH XJUI


.BQ EBUB TUSVDUVSFT JOTUFBE PG MJTUT PG UVQMFT ZPV DBO JNQPSU
%BUB.BQ BOE VTF B .BQ WFSTJPO PG lookup BMPOH XJUI fromList
UP BDDPNQMJTI UIF TBNF UIJOH XJUI UIBU EBUB TUSVDUVSF

Prelude> fmap c $ Data.Map.lookup 3 (fromList [(3, "hello")])


Just "Hello"

5IBU NBZ TFFN USJWJBM BU UIF NPNFOU CVU .BQ JT B GSF


RVFOUMZ VTFE EBUB TUSVDUVSF TP JUƊT XPSUI NFOUJPOJOH
/PX UIBU XF IBWF WBMVFT XSBQQFE JO B .BZCF DPOUFYU QFS
IBQT XFƊE MJLF UP BQQMZ TPNF GVODUJPOT UP UIFN 5IJT JT XIFSF
XF XBOU BQQMJDBUJWF PQFSBUJPOT "MUIPVHI JUƊT NPSF MJLFMZ UIBU
XFƊE IBWF GVODUJPOT GFUDIJOH EBUB GSPN TPNFXIFSF FMTF SBUIFS
UIBO IBWJOH JU BMM MJTUFE JO PVS DPEF ƶMF XFƊMM HP BIFBE BOE
EFƶOF TPNF WBMVFT JO B TPVSDF ƶMF GPS DPOWFOJFODF

import Control.Applicative

f x = lookup x [(3, "hello"), (4, "julie"), (5, "kbai")]


g y = lookup y [(7, "sup?"), (8, "chris"), (9, "aloha")]

h z = lookup z [(2, 3), (5, 6), (7, 8)]


m x = lookup x [(4, 10), (8, 13), (1, 9001)]

/PX XF XBOU UP MPPL UIJOHT VQ BOE BEE UIFN UPHFUIFS 8FƊMM


TUBSU XJUI TPNF TJNQMF PQFSBUJPOT PWFS UIFTF EBUB
$)"15&3  "11-*$"5*7& 

Prelude> f 3
Just "hello"
Prelude> g 8
Just "chris"
Prelude> (++) <$> f 3 <*> g 7
Just "hellosup?"
Prelude> (+) <$> h 5 <*> m 1
Just 9007
Prelude> (+) <$> h 5 <*> m 6
Nothing

4P XF ƶSTU fmap UIPTF GVODUJPOT PWFS UIF WBMVF JOTJEF UIF


ƶSTU .BZCF DPOUFYU JG JUƊT B +VTU WBMVF NBLJOH JU B QBSUJBMMZ
BQQMJFE GVODUJPO XSBQQFE JO B .BZCF DPOUFYU 5IFO XF VTF
UIF UJFƶHIUFS UP BQQMZ UIBU UP UIF TFDPOE WBMVF BHBJO XSBQQFE
JO B .BZCF *G FJUIFS WBMVF JT B /PUIJOH XF HFU /PUIJOH
8F DBO BHBJO EP UIF TBNF UIJOH XJUI liftA2

Prelude> liftA2 (++) (g 9) (f 4)


Just "alohajulie"
Prelude> liftA2 (^) (h 5) (m 4)
Just 60466176
Prelude> liftA2 (*) (h 5) (m 4)
Just 60
Prelude> liftA2 (*) (h 1) (m 1)
Nothing
$)"15&3  "11-*$"5*7& 

:PVS BQQMJDBUJWF DPOUFYU DBO BMTP TPNFUJNFT CF IO

(++) <$> getLine <*> getLine


(,) <$> getLine <*> getLine

5SZ JU /PX USZ VTJOH fmap UP HFU UIF MFOHUI PG UIF SFTVMUJOH
TUSJOH PG UIF ƶSTU FYBNQMF

&YFSDJTFT -PPLVQT

*O UIF GPMMPXJOH FYFSDJTFT ZPV XJMM OFFE UP VTF UIF GPMMPXJOH


UFSNT UP NBLF UIF FYQSFTTJPOT UZQFDIFDL

 QVSF

 (<$>)
-- or fmap

 (<*>)

.BLF UIF GPMMPXJOH FYQSFTTJPOT UZQFDIFDL

 added :: Maybe Integer


added = (+3) (lookup 3 $ zip [1, 2, 3] [4, 5, 6])
$)"15&3  "11-*$"5*7& 

 y :: Maybe Integer
y = lookup 3 $ zip [1, 2, 3] [4, 5, 6]

z :: Maybe Integer
z = lookup 2 $ zip [1, 2, 3] [4, 5, 6]

tupled :: Maybe (Integer, Integer)


tupled = (,) y z

 import Data.List (elemIndex)

x :: Maybe Int
x = elemIndex 3 [1, 2, 3, 4, 5]

y :: Maybe Int
y = elemIndex 4 [1, 2, 3, 4, 5]

max' :: Int -> Int -> Int


max' = max

maxed :: Maybe Int


maxed = max' x y
$)"15&3  "11-*$"5*7& 

 xs = [1, 2, 3]
ys = [4, 5, 6]

x :: Maybe Integer
x = lookup 3 $ zip xs ys

y :: Maybe Integer
y = lookup 2 $ zip xs ys

summed :: Maybe Integer


summed = sum $ (,) x y

*EFOUJUZ
5IF Identity UZQF IFSF JT B XBZ UP JOUSPEVDF TUSVDUVSF XJUIPVU
DIBOHJOH UIF TFNBOUJDT PG XIBU ZPVƊSF EPJOH 8FƊMM TFF JU VTFE
XJUI UIFTF UZQFDMBTTFT UIBU JOWPMWF GVODUJPO BQQMJDBUJPO BSPVOE
BOE PWFS TUSVDUVSF CVU UIJT UZQF JUTFMG JTOƊU WFSZ JOUFSFTUJOH BT
JU IBT OP TFNBOUJD ƷBWPS

4QFDJBMJ[JOH UIF UZQFT

)FSF JT XIBU UIF UZQF XJMM MPPL MJLF XIFO PVS TUSVDUVSF JT
Identity
$)"15&3  "11-*$"5*7& 

-- f ~ Identity
-- Applicative f =>
(<*>) :: f (a -> b) -> f a -> f b
(<*>) :: Identity (a -> b) -> Identity a -> Identity b

pure :: a -> f a
pure :: a -> Identity a

8IZ XPVME XF VTF *EFOUJUZ KVTU UP JOUSPEVDF TPNF TUSVDUVSF


8IBU JT UIF NFBOJOH PG BMM UIJT

Prelude> const <$> [1, 2, 3] <*> [9, 9, 9]


[1,1,1,2,2,2,3,3,3]
Prelude> const <$> Identity [1, 2, 3] <*> Identity [9, 9, 9]
Identity [1,2,3]

)BWJOH UIJT FYUSB CJU PG TUSVDUVSF BSPVOE PVS WBMVFT MJǒT UIF
const GVODUJPO GSPN NBQQJOH PWFS UIF MJTUT UP NBQQJOH PWFS
UIF *EFOUJUZ 8F IBWF UP HP PWFS BO ԕ TUSVDUVSF UP BQQMZ UIF
GVODUJPO UP UIF WBMVFT JOTJEF *G PVS ԕ JT UIF MJTU const BQQMJFT
UP UIF WBMVFT JOTJEF UIF MJTU BT XF TBX BCPWF *G UIF ԕ JT *EFOUJUZ
UIFO const USFBUT UIF MJTUT JOTJEF UIF *EFOUJUZ TUSVDUVSF BT TJOHMF
WBMVFT OPU TUSVDUVSF DPOUBJOJOH WBMVFT

&YFSDJTF *EFOUJUZ *OTUBODF

8SJUF BO "QQMJDBUJWF JOTUBODF GPS *EFOUJUZ


$)"15&3  "11-*$"5*7& 

newtype Identity a = Identity a


deriving (Eq, Ord, Show)

instance Functor Identity where


fmap = undefined

instance Applicative Identity where


pure = undefined
(<*>) = undefined

$POTUBOU
5IJT JT OPU TP EJƵFSFOU GSPN UIF *EFOUJUZ UZQF FYDFQU UIJT
OPU POMZ QSPWJEFT TUSVDUVSF JU BMTP BDUT MJLF UIF const GVODUJPO
*U TPSU PG UISPXT BXBZ B GVODUJPO BQQMJDBUJPO *G UIJT TFFNT
DPOGVTJOH JUƊT CFDBVTF JU JT )PXFWFS JU JT BMTP TPNFUIJOH UIBU
MJLF *EFOUJUZ IBT SFBMMJGF VTF DBTFT BOE ZPV XJMM TFF JU JO PUIFS
QFPQMFƊT DPEF *U DBO CF EJƸDVMU UP HFU VTFE UP VTJOH JU ZPVSTFMG
CVU XF KVTU LFFQ USZJOH
5IJT EBUBUZQF JT MJLF UIF const GVODUJPO JO UIBU JU UBLFT UXP
BSHVNFOUT CVU POF PG UIFN KVTU HFUT EJTDBSEFE *O UIF DBTF PG
UIF EBUBUZQF XF IBWF UP NBQ PVS GVODUJPO PWFS UIF BSHVNFOU
UIBU HFUT EJTDBSEFE 4P UIFSF JT OP WBMVF UP NBQ PWFS BOE UIF
GVODUJPO BQQMJDBUJPO KVTU EPFTOƊU IBQQFO
$)"15&3  "11-*$"5*7& 

4QFDJBMJ[JOH UIF UZQFT

"MM SJHIU TP IFSFƊT XIBU UIF UZQFT XJMM MPPL MJLF

-- f ~ Constant e

(<*>) :: f (a -> b) -> f a -> f b


(<*>) :: Constant e (a -> b) -> Constant e a -> Constant e b

pure :: a -> f a
pure :: a -> Constant e a

"OE IFSF BSF TPNF FYBNQMFT PG IPX JU XPSLT 5IFTF BSF


ZFT B CJU DPOUSJWFE CVU TIPXJOH ZPV SFBM DPEF XJUI UIJT JO JU
XPVME QSPCBCMZ NBLF JU NVDI IBSEFS GPS ZPV UP TFF XIBUƊT
BDUVBMMZ HPJOH PO

*Main> Constant (Sum 1) <*> Constant (Sum 2)


Constant {getConstant = Sum {getSum = 3}
Prelude> Constant undefined <*> Constant (Sum 2)
Constant (Sum {getSum = *** Exception: Prelude.undefined
*Main> pure 1
1
*Main> pure 1 :: Constant String Int
Constant {getConstant = ""}

*U DBOƊU EP BOZUIJOH CFDBVTF JU DBO POMZ IPME POUP UIF POF


WBMVF 5IF GVODUJPO EPFTOƊU FYJTU BOE UIF ԑ JT B HIPTU 4P ZPV
$)"15&3  "11-*$"5*7& 

VTF UIJT XIFO XIBUFWFS ZPV XBOU UP EP JOWPMWFT KVTU UISPXJOH


BXBZ B GVODUJPO BQQMJDBUJPO 8F LOPX JU TFFNT TPNFXIBU
DSB[Z CVU XF QSPNJTF UIFSF BSF SFBMMZ UJNFT SFBM DPEFST EP
UIJT JO SFBM DPEF 1JOLZ TXFBS

&YFSDJTF $POTUBOU *OTUBODF

8SJUF BO "QQMJDBUJWF JOTUBODF GPS $POTUBOU

newtype Constant a b =
Constant { getConstant :: a }
deriving (Eq, Ord, Show)

instance Functor (Constant a) where


fmap = undefined

instance Monoid a => Applicative (Constant a) where


pure = undefined
(<*>) = undefined

.BZCF "QQMJDBUJWF
8JUI .BZCF XFƊSF EPJOH TPNFUIJOH B CJU EJƵFSFOU GSPN BCPWF
8F TBX QSFWJPVTMZ IPX UP VTF fmap XJUI .BZCF CVU IFSF PVS
GVODUJPO JT BMTP FNCFEEFE JO B .BZCF TUSVDUVSF 5IFSFGPSF
XIFO ԕ JT .BZCF XFƊSF TBZJOH UIF GVODUJPO JUTFMG NJHIU OPU
$)"15&3  "11-*$"5*7& 

FYJTU CFDBVTF XFƊSF BMMPXJOH UIF QPTTJCJMJUZ PG UIF GVODUJPO UP


CF BQQMJFE CFJOH B /PUIJOH DBTF

4QFDJBMJ[JOH UIF UZQFT

)FSFƊT XIBU UIF UZQF MPPLT MJLF XIFO XFƊSF VTJOH .BZCF BT PVS
ԕ TUSVDUVSF

-- f ~ Maybe
(<*>) :: f (a -> b) -> f a -> f b
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b

pure :: a -> f a
pure :: a -> Maybe a

"SF ZPV SFBEZ UP WBMJEBUF TPNF QFSTPOT :FT :FT ZPV BSF

6TJOH UIF .BZCF "QQMJDBUJWF

$POTJEFS UIF GPMMPXJOH FYBNQMF XIFSF XF WBMJEBUF PVS JO


QVUT UP DSFBUF B WBMVF PG UZQF Maybe Person XIFSF UIF .BZCF JT
CFDBVTF PVS JOQVUT NJHIU CF JOWBMJE
$)"15&3  "11-*$"5*7& 

validateLength :: Int -> String -> Maybe String


validateLength maxLen s =
if (length s) > maxLen
then Nothing
else Just s

newtype Name = Name String deriving (Eq, Show)


newtype Address = Address String deriving (Eq, Show)

mkName :: String -> Maybe Name


mkName s = fmap Name $ validateLength 25 s

mkAddress :: String -> Maybe Address


mkAddress a = fmap Address $ validateLength 100 a

/PX XFƊMM NBLF B TNBSU DPOTUSVDUPS GPS B Person


$)"15&3  "11-*$"5*7& 

data Person =
Person Name Address
deriving (Eq, Show)

mkPerson :: String -> String -> Maybe Person


mkPerson n a =
case mkName n of
Nothing -> Nothing
Just n' ->
case mkAddress a of
Nothing -> Nothing
Just a' ->
Just $ Person n' a'

5IF QSPCMFN IFSF JT XIJMF XFƊWF TVDDFTTGVMMZ MFWFSBHFE fmap


GSPN 'VODUPS JO UIF TJNQMFS DBTFT PG mkName BOE mkAddress XF
DBOƊU SFBMMZ NBLF UIBU XPSL IFSF XJUI mkPerson -FUƊT JOWFTUJHBUF
XIZ

Prelude> :t fmap Person (mkName "Babe")


fmap Person (mkName "Babe") :: Maybe (Address -> Person)

5IJT IBT XPSLFE TP GBS GPS UIF ƶSTU BSHVNFOU UP UIF Person
DPOTUSVDUPS UIBU XFƊSF WBMJEBUJOH CVU XFƊWF IJU TPSU PG B SPBE
CMPDL $BO ZPV TFF UIF QSPCMFN

Prelude> let maybeAddy = (mkAddress "old macdonald's")


$)"15&3  "11-*$"5*7& 

Prelude> :t fmap (fmap Person (mkName "Babe")) maybeAddy

Couldn't match expected type ‘Address -> b’


with actual type ‘Maybe (Address -> Person)’

Possible cause: ‘fmap’ is applied to too many arguments


In the first argument of ‘fmap’, namely
‘(fmap Person (mkName "Babe"))’

In the expression:
fmap (fmap Person (mkName "Babe")) maybeAddy

5IF QSPCMFN JT UIBU PVS (a -> b) JT OPX IJEJOH JOTJEF Maybe


-FUƊT MPPL BU UIF UZQF PG fmap BHBJO

fmap :: Functor f => (a -> b) -> f a -> f b

.BZCF JT EFƶOJUFMZ B 'VODUPS CVU UIBUƊT OPU SFBMMZ HPJOH UP


IFMQ VT IFSF 8F OFFE UP CF BCMF UP NBQ B GVODUJPO FNCFEEFE
JO PVS ԕ "QQMJDBUJWF HJWFT VT XIBU XF OFFE IFSF

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

/PX MFUƊT TFF JG XF DBO XJFME UIJT OFX UPZ

Prelude> (fmap Person (mkName "Babe")) <*> maybeAddy


Just (Person (Name "Babe") (Address "old macdonald's"))
$)"15&3  "11-*$"5*7& 

/JDF SJHIU " MJUUMF VHMZ UIPVHI "T JU IBQQFOT $POUSPM"Q


QMJDBUJWF HJWFT VT BO JOƶY BMJBT GPS fmap DBMMFE <$> :PV TIPVME
QSPCBCMZ KVTU DBMM JU ƌGNBQƍ CVU UIF BVUIPST XPOƊU UFMM BOZCPEZ
JG ZPVƊSF TBZJOH ƌDBTINPOFZƍ JO ZPVS IFBE

Prelude> Person <$> mkName "Babe" <*> maybeAddy


Just (Person (Name "Babe") (Address "old macdonald's"))

.VDI CFUUFS 8F TUJMM VTF fmap WJB <$>


IFSF GPS UIF ƶSTU
MJǒJOH PWFS .BZCF BǒFS UIBU PVS (a -> b) JT IJEJOH JO UIF ԕ
XIFSF ԕ  .BZCF TP XF IBWF UP TUBSU VTJOH "QQMJDBUJWF UP LFFQ
NBQQJOH PWFS UIBU
8F DBO OPX VTF B NVDI TIPSUFS BOE OJDFS EFƶOJUJPO PG
mkPerson

mkPerson :: String -> String -> Maybe Person


mkPerson n a =
Person <$> mkName n <*> mkAddress a

"T BO BEEJUJPOBM CPOVT UIJT JT OPX GBS MFTT BOOPZJOH UP


FYUFOE JG XF BEEFE OFX ƶFMET BT XFMM

#SFBLJOH EPXO UIF FYBNQMF XF KVTU TBX

8FƊSF HPJOH UP HJWF UIF 'VODUPS BOE "QQMJDBUJWF JOTUBODFT GPS


.BZCF UIF TBNF USFBUNFOU XF HBWF GPME 5IJT XJMM CF B CJU
MPOH *U JT QPTTJCMF UIBU TPNF PG UIJT XJMM TFFN MJLF UPP NVDI
$)"15&3  "11-*$"5*7& 

EFUBJM SFBE JU UP XIBUFWFS EFQUI ZPV GFFM ZPV OFFE UP *U XJMM
TJU IFSF QBUJFOUMZ XBJUJOH UP TFF JG ZPV FWFS OFFE UP DPNF CBDL
BOE SFBE JU NPSF DMPTFMZ

.BZCF 'VODUPS BOE UIF /BNF DPOTUSVDUPS

instance Functor Maybe where


fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)

instance Applicative Maybe where


pure = Just

Nothing <*> _ = Nothing


_ <*> Nothing = Nothing
Just f <*> Just a = Just (f a)

5IF "QQMJDBUJWF JOTUBODF JT OPU FYBDUMZ UIF TBNF BT UIF JO


TUBODF JO CBTF CVU UIBUƊT GPS TJNQMJƶDBUJPO 'PS ZPVS QVSQPTFT
JU QSPEVDFT UIF TBNF SFTVMUT
'JSTU UIF GVODUJPO BOE EBUBUZQF EFƶOJUJPOT GPS PVS GVODUPS
XSJUFVQ GPS IPX XFƊSF VTJOH UIF validateLength GVODUJPO XJUI
/BNF BOE "EESFTT
$)"15&3  "11-*$"5*7& 

validateLength :: Int -> String -> Maybe String


validateLength maxLen s =
if (length s) > maxLen
then Nothing
else Just s

newtype Name =
Name String deriving (Eq, Show)

newtype Address =
Address String deriving (Eq, Show)

mkName :: String -> Maybe Name


mkName s = fmap Name $ validateLength 25 s

mkAddress :: String -> Maybe Address


mkAddress a = fmap Address $ validateLength 100 a

/PX XFƊSF HPJOH UP TUBSU ƶMMJOH JO UIF EFƶOJUJPOT BOE FY


QBOEJOH UIFN FRVBUJPOBMMZ MJLF XF EJE JO UIF DIBQUFS PO GPMET
'JSTU XF BQQMZ mkName UP UIF WBMVF "babe" TP UIBU Ԣ JT CPVOE
UP UIBU TUSJOH

mkName s = fmap Name $ validateLength 25 s


mkName "babe" = fmap Name $ validateLength 25 "babe"
$)"15&3  "11-*$"5*7& 

/PX XF OFFE UP ƶHVSF PVU XIBU validateLength JT BCPVU TJODF


UIBU IBT UP CF FWBMVBUFE CFGPSF XF LOPX XIBU fmap JT NBQQJOH
PWFS )FSF XFƊSF BQQMZJOH JU UP  BOE ƍCBCFƍ FWBMVBUJOH UIF
MFOHUI PG UIF TUSJOH ƍCBCFƍ BOE UIFO EFUFSNJOJOH XIJDI CSBODI
JO UIF JGUIFOFMTF XJOT

validateLength :: Int -> String -> Maybe String


validateLength 25 "babe" =
if (length "babe") > 25
then Nothing
else Just "babe"

if 4 > 25
then Nothing
else Just "babe"

-- 4 isn't greater than 25, so:


validateLength 25 "babe" = Just "babe"

/PX XFƊSF HPJOH UP SFQMBDF validateLength BQQMJFE UP  BOE


ƍCBCFƍ XJUI XIBU JU FWBMVBUFE UP UIFO ƶHVSF PVU XIBU UIF fmap
Name PWFS Just "babe" CVTJOFTT JT BCPVU

mkName "babe" = fmap Name $ Just "babe"

fmap Name $ Just "babe"


$)"15&3  "11-*$"5*7& 

,FFQJOH JO NJOE UIF UZQF PG fmap GSPN 'VODUPS XF TFF UIF


EBUB DPOTUSVDUPS /BNF JT UIF GVODUJPO (a -> b) XFƊSF NBQQJOH
PWFS TPNF 'VODUPSJBM ԕ *O UIJT DBTF ԕ JT .BZCF 5IF Ԑ JO ԕ Ԑ
JT 4USJOH

(a -> b) -> f a -> f b

:t Name :: (String -> Name)


:t Just "babe" :: Maybe String

(a -> b) -> f a -> f b


(String -> Name) -> Maybe String -> Maybe Name

4JODF XF LOPX XFƊSF EFBMJOH XJUI UIF 'VODUPS JOTUBODF GPS


.BZCF XF DBO JOMJOF UIBU GVODUJPOƊT EFƶOJUJPO UPP
$)"15&3  "11-*$"5*7& 

fmap _ Nothing = Nothing


fmap f (Just a) = Just (f a)

-- We have (Just "babe") so skipping Nothing case


-- fmap _ Nothing = Nothing

fmap f (Just a) = Just (f a)


fmap Name (Just "babe") = Just (Name "babe")

mkName "babe" = fmap Name $ Just "babe"


mkName "babe" = Just (Name "babe")
-- f b

.BZCF "QQMJDBUJWF BOE 1FSTPO

data Person =
Person Name Address
deriving (Eq, Show)

'JSTU XFƊMM CF VTJOH UIF 'VODUPS UP NBQ UIF 1FSTPO EBUB DPO
TUSVDUPS PWFS UIF Maybe Name WBMVF 6OMJLF /BNF BOE "EESFTT
1FSTPO UBLFT UXP BSHVNFOUT SBUIFS UIBO POF
$)"15&3  "11-*$"5*7& 

Person <$> Just (Name "babe") <*> Just (Address "farm")

fmap Person (Just (Name "babe"))

:t Person :: Name -> Address -> Person

:t Just (Name "babe") :: Maybe Name

(a -> b) -> f a -> f b


(Name -> Address -> Person)
a -> b
-> Maybe Name -> Maybe (Address -> Person)
f a f b
$)"15&3  "11-*$"5*7& 

fmap _ Nothing = Nothing


fmap f (Just a) = Just (f a)

fmap Person (Just (Name "babe"))

f :: Person
a :: Name "babe"

-- We skip this pattern match because we have Just


-- fmap _ Nothing = Nothing

fmap f (Just a) =
Just (f a)

fmap Person (Just (Name "babe")) =


Just (Person (Name "babe"))

5IF QSPCMFN JT Person (Name "babe") JT BXBJUJOH BOPUIFS BS


HVNFOU UIF BEESFTT TP JUƊT B QBSUJBMMZ BQQMJFE GVODUJPO 5IBUƊT
PVS (a -> b) JO UIF UZQF PG "QQMJDBUJWFƊT (<*>) 5IF ԕ XSBQ
QJOH PVS (a -> b) JT UIF .BZCF XIJDI SFTVMUT GSPN VT QPTTJCMZ
OPU IBWJOH IBE BO Ԑ UP NBQ PWFS UP CFHJO XJUI SFTVMUJOH JO B
/PUIJOH WBMVF
$)"15&3  "11-*$"5*7& 

-- Person is awaiting another argument


:t Just (Person (Name "babe")) :: Maybe (Address -> Person)

:t Just (Address "farm") :: Maybe Address

-- We want to apply the partially applied (Person "babe")


-- inside the 'Just' to the "farm" inside the Just.

Just (Person (Name "babe")) <*> Just (Address "farm")

4P TJODF UIF GVODUJPO XF XBOU UP NBQ JT JOTJEF UIF TBNF


TUSVDUVSF BT UIF WBMVF XF XBOU UP BQQMZ JU UP XF OFFE UIF
"QQMJDBUJWF (<*>) *O UIF GPMMPXJOH XF SFNJOE ZPV PG XIBU UIF
UZQF MPPLT MJLF BOE IPX UIF UZQF TQFDJBMJ[FT UP UIJT BQQMJDBUJPO

f (a -> b) -> f a -> f b

Maybe (Address -> Person) -> Maybe Address -> Maybe Person
f ( a -> b ) -> f a -> f b

8F LOPX XFƊSF VTJOH UIF .BZCF "QQMJDBUJWF TP XF DBO


HP BIFBE BOE JOMJOF UIF EFƶOJUJPO PG UIF .BZCF "QQMJDBUJWF
3FNJOEFS UIBU UIJT WFSTJPO PG UIF "QQMJDBUJWF JOTUBODF JT TJN
QMJƶFE GSPN UIF POF JO ()$ TP QMFBTF EPOƊU FNBJM VT UP UFMM VT
PVS JOTUBODF JT XSPOH
$)"15&3  "11-*$"5*7& 

instance Applicative Maybe where


pure = Just

Nothing <*> _ = Nothing


_ <*> Nothing = Nothing
Just f <*> Just a = Just (f a)

8F LOPX XF DBO JHOPSF UIF Nothing DBTFT CFDBVTF PVS GVOD


UJPO JT Just PVS WBMVF JT JustBOE PVS DBVTF JT KVTU +VTUƒLJE
EJOH
*G XF ƶMM JO PVS QBSUJBMMZ BQQMJFE 1FSTPO DPOTUSVDUPS GPS ԕ
BOE PVS "EESFTT WBMVF GPS Ԑ JUƊT OPU UPP IBSE UP TFF IPX UIF
ƶOBM SFTVMU ƶUT

-- Neither function nor value are Nothing,


-- so we skip these two cases
-- Nothing <*> _ = Nothing
-- _ <*> Nothing = Nothing

Just f <*> Just a = Just (f a)


Just (Person (Name "babe")) <*> Just (Address "farm") =
Just (Person (Name "babe") (Address "farm"))
$)"15&3  "11-*$"5*7& 

#FGPSF XF NPPPPWF PO

data Cow = Cow {


name :: String
, age :: Int
, weight :: Int
} deriving (Eq, Show)

noEmpty :: String -> Maybe String


noEmpty "" = Nothing
noEmpty str = Just str

noNegative :: Int -> Maybe Int


noNegative n | n >= 0 = Just n
| otherwise = Nothing
$)"15&3  "11-*$"5*7& 

-- Validating to get rid of empty strings, negative numbers


cowFromString :: String -> Int -> Int -> Maybe Cow
cowFromString name' age' weight' =
case noEmpty name' of
Nothing -> Nothing
Just nammy ->
case noNegative age' of
Nothing -> Nothing
Just agey ->
case noNegative weight' of
Nothing -> Nothing
Just weighty ->
Just (Cow nammy agey weighty)

cowFromString JTƒCBE :PV DBO QSPCBCMZ UFMM #VU CZ UIF VTF


PG "QQMJDBUJWF JU DBO CF JNQSPWFE

-- you'll need to import this if you have GHC <7.10

import Control.Applicative

cowFromString' :: String -> Int -> Int -> Maybe Cow


cowFromString' name' age' weight' =
Cow <$> noEmpty name'
<*> noNegative age'
<*> noNegative weight'
$)"15&3  "11-*$"5*7& 

0S JG XF XBOU PUIFS )BTLFMMFST UP UIJOL XFƊSF SFBMMZ DPPM


BOE IJQ

cowFromString'' :: String -> Int -> Int -> Maybe Cow


cowFromString'' name' age' weight' =
liftA3 Cow (noEmpty name')
(noNegative age')
(noNegative weight')

4P XFƊSF UBLJOH BEWBOUBHF PG UIF .BZCF "QQMJDBUJWF IFSF


8IBU EPFT UIBU MPPL MJLF 'JSTU XFƊMM VTF UIF JOƶY TZOUBY GPS
GNBQ <$> BOE BQQMZ <*>

Prelude> let cow1 = Cow <$> noEmpty "Bess"

Prelude> :t cow1
cow1 :: Maybe (Int -> Int -> Cow)

Prelude> let cow2 = cow1 <*> noNegative 1

Prelude> :t cow2
cow2 :: Maybe (Int -> Cow)

Prelude> let cow3 = cow2 <*> noNegative 2

Prelude> :t cow3
cow3 :: Maybe Cow
$)"15&3  "11-*$"5*7& 

5IFO XJUI MJǒ"

Prelude> let cow1 = liftA3 Cow

Prelude> :t cow1
cow1 :: Applicative f => f String -> f Int -> f Int -> f Cow

Prelude> let cow2 = cow1 (noEmpty "blah")

Prelude> :t cow2
cow2 :: Maybe Int -> Maybe Int -> Maybe Cow

Prelude> let cow3 = cow2 (noNegative 1)

Prelude> :t cow3
cow3 :: Maybe Int -> Maybe Cow

Prelude> let cow4 = cow3 (noNegative 2)

Prelude> :t cow4
cow4 :: Maybe Cow

4P GSPN B TJNQMJƶFE QPJOU PG WJFX "QQMJDBUJWF JT SFBMMZ KVTU


B XBZ PG TBZJOH
$)"15&3  "11-*$"5*7& 

-- we fmap'd my function over some functorial ``f''


-- or it already was in ``f'' somehow

-- f ~ Maybe
cow1 :: Maybe (Int -> Int -> Cow)
cow1 = fmap Cow (noEmpty "Bess")

-- and we hit a situation where want to map


-- f (a -> b)
-- not just (a -> b)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
-- over some f a
-- to get an f b

cow2 :: Maybe (Int -> Cow)


cow2 = cow1 <*> noNegative 1

"T B SFTVMU ZPV NBZ CF BCMF UP JNBHJOF ZPVSTFMG TBZJOH ƌ*


XBOU UP EP TPNFUIJOH LJOEB MJLF BO GNBQ CVU NZ GVODUJPO JT
FNCFEEFE JO UIF GVODUPSJBM TUSVDUVSF UPP OPU KVTU UIF WBMVF *
XBOU UP BQQMZ NZ GVODUJPO UPƍ 5IJT JT B CBTJD NPUJWBUJPO GPS
"QQMJDBUJWF
8JUI UIF "QQMJDBUJWF JOTUBODF GPS .BZCF XIBU XFƊSF EPJOH
JT FOSJDIJOH GVODUPSJBM BQQMJDBUJPO XJUI UIF BEEJUJPOBM QSPWJTP
UIBU ƌ* NBZ OPU IBWF B GVODUJPO BU BMMƍ
$)"15&3  "11-*$"5*7& 

8F DBO TFF UIJT JO UIF GPMMPXJOH TQFDJBMJ[BUJPO PG UIF BQQMZ


GVODUJPO (<*>)

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

f ~ Maybe

maybeApply :: Maybe (a -> b) -> Maybe a -> Maybe b


maybeFmap :: (a -> b) -> Maybe a -> Maybe b

-- maybeFmap is just fmap's type specialized to Maybe

:PV DBO UFTU UIFTF TQFDJBMJ[BUJPOT NPSF DPODSFUF WFSTJPOT

PG UIF UZQFT JO UIF 3&1-

Prelude> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b

Prelude> :t (<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b


(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
:: Maybe (a -> b) -> Maybe a -> Maybe b

Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b

Prelude> :t fmap :: (a -> b) -> Maybe a -> Maybe b


$)"15&3  "11-*$"5*7& 

fmap :: (a -> b) -> Maybe a -> Maybe b


:: (a -> b) -> Maybe a -> Maybe b

*G ZPV NBLF BOZ NJTUBLFT UIF 3&1- XJMM MFU ZPV LOPX

Prelude> :t fmap :: (a -> b) -> Maybe a -> f b

Couldn't match type ‘f1’ with ‘Maybe’


‘f1’ is a rigid type variable bound by
an expression type signature:
(a1 -> b1) -> Maybe a1 -> f1 b1

Expected type: (a1 -> b1) -> Maybe a1 -> f1 b1


Actual type: (a1 -> b1) -> f1 a1 -> f1 b1
In the expression: fmap :: (a -> b) -> Maybe a -> f b

Prelude> :t (<*>) :: Maybe (a -> b) -> Maybe a -> f b

Couldn't match type ‘f1’ with ‘Maybe’


‘f1’ is a rigid type variable bound by
an expression type signature:
Maybe (a1 -> b1) -> Maybe a1 -> f1 b1

Expected type: Maybe (a1 -> b1) -> Maybe a1 -> f1 b1


Actual type: f1 (a1 -> b1) -> f1 a1 -> f1 b1
$)"15&3  "11-*$"5*7& 

In the expression:
(<*>) :: Maybe (a -> b) -> Maybe a -> f b

&YFSDJTF 'JYFS 6QQFS

(JWFO UIF GVODUJPO BOE WBMVFT QSPWJEFE VTF (<$>) GSPN 'VOD
UPS (<*>) BOE pure GSPN UIF "QQMJDBUJWF UZQFDMBTT UP ƶMM JO NJTT
JOH CJUT PG UIF CSPLFO DPEF UP NBLF JU XPSL

 const <$> Just "Hello" <*> "World"

 (,,,) Just 90 <*> Just 10 Just "Tierness" [1, 2, 3]

 "QQMJDBUJWF MBXT


"ǒFS FYBNJOJOH UIF MBX UFTU FBDI PG UIF FYQSFTTJPOT JO UIF
3&1-

 *EFOUJUZ
)FSF JT UIF EFƶOJUJPO PG UIF JEFOUJUZ MBX

pure id <*> v = v

5P TFF FYBNQMFT PG UIJT MBX FWBMVBUF UIFTF FYQSFTTJPOT


$)"15&3  "11-*$"5*7& 

pure id <*> [1..5]

pure id <*> Just "Hello Applicative"

pure id <*> Nothing

pure id <*> Left "Error'ish"

pure id <*> Right 8001

-- ((->) a) has an instance


pure id <*> (+1) $ 2

"T ZPV NBZ SFDBMM 'VODUPS IBT B TJNJMBS JEFOUJUZ MBX BOE
DPNQBSJOH UIFN EJSFDUMZ NJHIU IFMQ ZPV TFF XIBUƊT IBQ
QFOJOH

id [1..5]

fmap id [1..5]

pure id <*> [1..5]

5IF JEFOUJUZ MBX TUBUFT UIBU BMM UISFF PG UIPTF TIPVME CF


FRVBM :PV DBO UFTU UIFN GPS FRVBMJUZ JO ZPVS 3&1- PS ZPV
DPVME XSJUF B TJNQMF UFTU UP HFU UIF BOTXFS 4P XIBUƊT pure
$)"15&3  "11-*$"5*7& 

EPJOH GPS VT *UƊT FNCFEEJOH PVS id GVODUJPO JOUP TPNF


TUSVDUVSF TP UIBU XF DBO VTF apply JOTUFBE PG fmap

 $PNQPTJUJPO
)FSF JT UIF EFƶOJUJPO PG UIF DPNQPTJUJPO MBX GPS BQQMJDB
UJWFT

pure (.) <*> u <*> v <*> w = u <*> (v <*> w)

:PV NBZ ƶOE UIF TZOUBY B CJU VOVTVBM BOE EJƸDVMU UP SFBE
IFSF 5IJT JT TJNJMBS UP UIF MBX PG DPNQPTJUJPO GPS 'VOD
UPS *U JT UIF MBX TUBUJOH UIBU UIF SFTVMU PG DPNQPTJOH PVS
GVODUJPOT ƶSTU BOE UIFO BQQMZJOH UIFN BOE UIF SFTVMU PG
BQQMZJOH UIF GVODUJPOT ƶSTU UIFO DPNQPTJOH UIFN TIPVME
CF UIF TBNF 8FƊSF VTJOH UIF DPNQPTJUJPO PQFSBUPS BT B
QSFƶY JOTUFBE PG UIF NPSF VTVBM JOƶY BOE VTJOH pure JO PS
EFS UP FNCFE UIBU PQFSBUPS JOUP UIF BQQSPQSJBUF TUSVDUVSF
TP UIBU JU DBO XPSL XJUI apply

pure (.) <*> [(+1)] <*> [(*2)] <*> [1, 2, 3]

[(+1)] <*> ([(*2)] <*> [1, 2, 3])

pure (.) <*> Just (+1) <*> Just (*2) <*> Just 1

Just (+1) <*> (Just (*2) <*> Just 1)


$)"15&3  "11-*$"5*7& 

5IJT MBX JT NFBOU UP FOTVSF UIBU UIFSF BSF OP TVSQSJTFT


SFTVMUJOH GSPN DPNQPTJOH ZPVS GVODUJPO BQQMJDBUJPOT

 )PNPNPSQIJTN
" IPNPNPSQIJTN JT B TUSVDUVSFQSFTFSWJOH NBQ CFUXFFO
UXP BMHFCSBJD TUSVDUVSFT 5IF FƵFDU PG BQQMZJOH B GVOD
UJPO UIBU JT FNCFEEFE JO TPNF TUSVDUVSF UP B WBMVF UIBU JT
FNCFEEFE JO TPNF TUSVDUVSF TIPVME CF UIF TBNF BT BQ
QMZJOH B GVODUJPO UP B WBMVF XJUIPVU BƵFDUJOH BOZ PVUTJEF
TUSVDUVSF

pure f <*> pure x = pure (f x)

5IBUƊT UIF TUBUFNFOU PG UIF MBX )FSFƊT IPX JU MPPLT JO


QSBDUJDF

pure (+1) <*> pure 1

pure ((+1) 1)

5IPTF UXP MJOFT PG DPEF TIPVME HJWF ZPV UIF TBNF SFTVMU
*O GBDU UIF SFTVMU ZPV TFF GPS UIPTF TIPVME CF JOEJTUJO
HVJTIBCMF GSPN UIF SFTVMU PG

(+1) 1

#FDBVTF UIF ƌTUSVDUVSFƍ UIBU pure JT QSPWJEJOH UIFSF JTOƊU


SFBMMZ NFBOJOHGVM 4P ZPV DBO UIJOL PG UIJT MBX BT IBWJOH
$)"15&3  "11-*$"5*7& 

UP EP XJUI UIF NPOPJEBM QBSU PG UIF BQQMJDBUJWF EFBM UIF


SFTVMU TIPVME CF UIF SFTVMU PG UIF GVODUJPO BQQMJDBUJPO XJUI
PVU EPJOH BOZUIJOH PUIFS UIBO DPNCJOJOH UIF TUSVDUVSF
CJUT +VTU BT XF TBX IPX fmap JT SFBMMZ KVTU B TQFDJBM UZQF PG
GVODUJPO BQQMJDBUJPO UIBU JHOPSFT B DPOUFYU PS TVSSPVOE
JOH TUSVDUVSF BQQMJDBUJWF JT BMTP GVODUJPO BQQMJDBUJPO UIBU
QSFTFSWFT TUSVDUVSF )PXFWFS XJUI BQQMJDBUJWF TJODF UIF
GVODUJPO CFJOH BQQMJFE BMTP IBT TUSVDUVSF UIF TUSVDUVSFT
IBWF UP CF NPOPJEBM BOE DPNF UPHFUIFS JO TPNF GBTIJPO

pure (+1) <*> pure 1 :: Maybe Int

pure ((+1) 1) :: Maybe Int

5IPTF UXP SFTVMUT TIPVME BHBJO CF UIF TBNF CVU UIJT UJNF
UIF TUSVDUVSF JT CFJOH QSPWJEFE CZ .BZCF TP XJMM UIF SFTVMU
PG

(+1) 1

CF FRVBM UIJT UJNF BSPVOE


)FSF BSF B DPVQMF NPSF FYBNQMFT UP USZ PVU

pure (+1) <*> pure 1 :: [Int]

pure (+1) <*> pure 1 :: Either a Int


$)"15&3  "11-*$"5*7& 

5IF HFOFSBM JEFB PG UIF IPNPNPSQIJTN MBX JT UIBU BQQMZ


JOH UIF GVODUJPO EPFTOƊU DIBOHF UIF TUSVDUVSF BSPVOE UIF
WBMVFT

 *OUFSDIBOHF
8F CFHJO BHBJO CZ MPPLJOH BU UIF EFƶOJUJPO PG UIF JOUFS
DIBOHF MBX

u <*> pure y = pure ($ y) <*> u

*U NJHIU IFMQ UP CSFBL UIBU EPXO B CJU 5P UIF MFǒ PG <*>


NVTU BMXBZT CF B GVODUJPO FNCFEEFE JO TPNF TUSVDUVSF
*O UIF BCPWF EFƶOJUJPO Ԥ SFQSFTFOUT B GVODUJPO FNCFEEFE
JO TPNF TUSVDUVSF

Just (+2) <*> pure 2


-- u <*> pure y
-- equals
Just 4

5IF SJHIU TJEF PG UIF EFƶOJUJPO NJHIU CF B CJU MFTT PCWJPVT


#Z TFDUJPOJOH UIF $ GVODUJPO BQQMJDBUJPO PQFSBUPS XJUI
UIF Ԩ XF DSFBUF BO FOWJSPONFOU JO XIJDI UIF Ԩ JT UIFSF
BXBJUJOH B GVODUJPO UP BQQMZ UP JU -FUƊT USZ MJOJOH VQ UIF
UZQFT BHBJO BOE TFF JG UIBU DMFBST UIJT VQ
$)"15&3  "11-*$"5*7& 

pure ($ 2) <*> Just (+ 2)

-- Remember, ($ 2) can become more concrete


($ 2) :: Num a => (a -> b) -> b
Just (+ 2) :: Num a => Maybe (a -> a)

*G ZPVƊSF B CJU DPOGVTFE CZ ($ 2) LFFQ JO NJOE UIBU UIJT


JT TFDUJPOJOH UIF EPMMBSTJHO PQFSBUPS BOE BQQMZJOH UIF
TFDPOE BSHVNFOU POMZ OPU UIF ƶSTU "T B SFTVMU UIF UZQF
DIBOHFT JO UIF GPMMPXJOH NBOOFS

-- These are the same


($ 2)
\f -> f $ 2

($) :: (a -> b) -> a -> b


($ 2) :: (a -> b) -> b

5IFO DPODSFUJOH UIF UZQFT PG ApplicativeƊT NFUIPET


$)"15&3  "11-*$"5*7& 

mPure :: a -> Maybe a


mPure = pure

embed :: Num a => Maybe ((a -> b) -> b)


embed = mPure ($ 2)

mApply :: Maybe ((a -> b) -> b)


-> Maybe (a -> b)
-> Maybe b
mApply = (<*>)

myResult = pure ($ 2) `mApply` Just (+2)


-- myResult == Just 4

5IFO USBOTMBUJOH UIF UZQFT TJEF CZ TJEF XJUI EJƵFSFOU


MFUUFST GPS TPNF PG UIF UZQF WBSJBCMFT UP BWPJE DPOGVTJPO
XIFO DPNQBSJOH UIF PSJHJOBM UZQF XJUI UIF NPSF DPODSFUF
GPSN

(<*>) :: Applicative f
=> f (x -> y)
-> f x
-> f y
$)"15&3  "11-*$"5*7& 

mApply :: Maybe ((a -> b) -> b)


-> Maybe (a -> b)
-> Maybe b

f ~ Maybe
x ~ (a -> b)
y ~ b
(x -> y) ~ (a -> b) -> b

"DDPSEJOH UP UIF JOUFSDIBOHF MBX UIJT TIPVME CF USVF

(Just (+2) <*> pure 2)


== (pure ($ 2) <*> Just (+2))

"OE ZPV DBO TFF XIZ UIBU TIPVME CF USVF CFDBVTF EFTQJUF
UIF XFJSE TZOUBY UIF UXP GVODUJPOT BSF EPJOH UIF TBNF
KPC )FSF BSF TPNF NPSF FYBNQMFT GPS ZPV UP USZ PVU

[(+1), (*2)] <*> pure 1

pure ($ 1) <*> [(+1), (*2)]

Just (+3) <*> pure 1

pure ($ 1) <*> Just (+3)


$)"15&3  "11-*$"5*7& 

&WFSZ "QQMJDBUJWF JOTUBODF ZPV XSJUF TIPVME PCFZ UIPTF GPVS


MBXT 5IJT LFFQT ZPVS DPEF DPNQPTBCMF BOE GSFF PG VOQMFBTBOU
TVSQSJTFT

 :PV LOFX UIJT XBT DPNJOH


2VJDL$IFDLJOH UIF "QQMJDBUJWF MBXT :PV TIPVME IBWF HPU
UIF HJTU PG IPX UP XSJUF QSPQFSUJFT CBTFE PO MBXT TP XFƊSF
HPJOH UP VTF B QSFFYJTUJOH MJCSBSZ UIJT UJNF $POBM &MMJPUU IBT
B OJDF MJCSBSZ DBMMFE DIFDLFST PO )BDLBHF BOE (JUIVC XIJDI
QSPWJEFT TPNF OJDF QSFFYJTUJOH QSPQFSUJFT BOE VUJMJUJFT GPS
2VJDL$IFDL
"ǒFS JOTUBMMJOH DIFDLFST XF DBO SFVTF UIF FYJTUJOH QSPQFSUJFT
GPS WBMJEBUJOH .POPJET BOE 'VODUPST UP SFWJTJU XIBU XF EJE
QSFWJPVTMZ
$)"15&3  "11-*$"5*7& 

module BadMonoid where

import Data.Monoid
import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes

data Bull =
Fools
| Twoo
deriving (Eq, Show)

instance Arbitrary Bull where


arbitrary =
frequency [ (1, return Fools)
, (1, return Twoo) ]

instance Monoid Bull where


mempty = Fools
mappend _ _ = Fools

instance EqProp Bull where (=-=) = eq

main :: IO ()
main = quickBatch (monoid Twoo)
$)"15&3  "11-*$"5*7& 

5IFSF BSF TPNF EJƵFSFODFT IFSF XPSUI OPUJOH 0OF JT UIBU


XF EPOƊU IBWF UP EFƶOF UIF .POPJE MBXT BT 2VJDL$IFDL QSPQFS
UJFT PVSTFMWFT UIFZ BSF BMSFBEZ CVOEMFE JOUP B TestBatch DBMMFE
monoid "OPUIFS JT UIBU XF OFFE UP EFƶOF EqProp GPS PVS DVTUPN
EBUBUZQF 5IJT JT TUSBJHIUGPSXBSE CFDBVTF DIFDLFST FYQPSUT B
GVODUJPO DBMMFE eq XIJDI SFVTFT UIF QSFFYJTUJOH Eq JOTUBODF
GPS UIF EBUBUZQF 'JOBMMZ XFƊSF QBTTJOH B WBMVF PG PVS UZQF
UP monoid TP JU LOPXT XIJDI Arbitrary JOTUBODF UP VTF UP HFU
SBOEPN WBMVFT ƈ OPUF JU EPFTOƊU BDUVBMMZ VTF UIJT WBMVF GPS
BOZUIJOH
5IFO XF DBO SVO main UP LJDL JU PƵ BOE TFF IPX JU HPFT

Prelude> main

monoid:
left identity: *** Failed! Falsifiable (after 1 test):
Twoo
right identity: *** Failed! Falsifiable (after 2 tests):
Twoo
associativity: +++ OK, passed 500 tests.

"T XF FYQFDU JU XBT BCMF UP GBMTJGZ MFǒ BOE SJHIU JEFOUJUZ GPS
Bull /PX MFUT UFTU B QSFFYJTUJOH "QQMJDBUJWF JOTUBODF TVDI
BT MJTU BOE NBZCF 5IF UZQF GPS UIF TestBatch XIJDI WBMJEBUFT
"QQMJDBUJWF JOTUBODFT JT B CJU HOBSMZ TP QMFBTF CFBS XJUI VT
$)"15&3  "11-*$"5*7& 

applicative
:: (Show a, Show (m a), Show (m (a -> b)), Show (m (b -> c)),
Applicative m, CoArbitrary a, EqProp (m a), EqProp (m b),
EqProp (m c), Arbitrary a, Arbitrary b, Arbitrary (m a),
Arbitrary (m (a -> b)), Arbitrary (m (b -> c))) =>
m (a, b, c) -> TestBatch

'JSTU B USJDL GPS NBOBHJOH GVODUJPOT MJLF UIJT 8F LOPX JUƊT


HPJOH UP XBOU "SCJUSBSZ JOTUBODFT GPS UIF "QQMJDBUJWF TUSVDUVSF
GVODUJPOT GSPN Ԑ UP ԑ ԑ UP Ԓ
FNCFEEFE JO UIBU TUSVDUVSF BOE
UIBU JU XBOUT &R1SPQ JOTUBODFT 5IBUƊT BMM XFMM BOE HPPE CVU
XF DBO JHOPSF UIBU

-- :: (Show a, Show (m a), Show (m (a -> b)), Show (m (b -> c)),


-- Applicative m, CoArbitrary a, EqProp (m a), EqProp (m b),
-- EqProp (m c), Arbitrary a, Arbitrary b, Arbitrary (m a),
-- Arbitrary (m (a -> b)), Arbitrary (m (b -> c))) =>
m (a, b, c) -> TestBatch

8F KVTU DBSF BCPVU m (a, b, c) -> TestBatch 8F DPVME QBTT


BO BDUVBM WBMVF HJWJOH VT PVS "QQMJDBUJWF TUSVDUVSF BOE UISFF
WBMVFT XIJDI DPVME CF PG EJƵFSFOU UZQF CVU EPOƊU IBWF UP
CF 8F DPVME BMTP QBTT B CPUUPN XJUI B UZQF BTTJHOFE UP MFU JU
LOPX XIBU UP SBOEPNMZ HFOFSBUF GPS WBMJEBUJOH UIF "QQMJDBUJWF
JOTUBODF

Prelude> quickBatch $ applicative [("b", "w", 1)]


$)"15&3  "11-*$"5*7& 

applicative:
identity: +++ OK, passed 500 tests.
composition: +++ OK, passed 500 tests.
homomorphism: +++ OK, passed 500 tests.
interchange: +++ OK, passed 500 tests.
functor: +++ OK, passed 500 tests.

/PUF UIBU JU EFGBVMUFE UIF 1 :: Num a => a JO PSEFS UP OPU


IBWF BO BNCJHVPVT UZQF 8F XPVMEƊWF IBE UP TQFDJGZ UIBU
PVUTJEF PG ()$J *O UIF GPMMPXJOH FYBNQMF XFƊMM VTF B CPUUPN
UP ƶSF UIF UZQFDMBTT EJTQBUDI

Prelude> let trigger = undefined :: [(String, String, Int)]


Prelude> quickBatch (applicative trigger)

applicative:
identity: +++ OK, passed 500 tests.
composition: +++ OK, passed 500 tests.
homomorphism: +++ OK, passed 500 tests.
interchange: +++ OK, passed 500 tests.
functor: +++ OK, passed 500 tests.

"HBJO JUƊT OPU FWBMVBUJOH UIF WBMVF ZPV QBTT JU 5IBU WBMVF
JT KVTU UP MFU JU LOPX XIBU UZQFT UP VTF
$)"15&3  "11-*$"5*7& 

 ;JQ-JTU .POPJE


5IF EFGBVMU NPOPJE PG MJTUT JO UIF ()$ 1SFMVEF JT DPODBUF
OBUJPO CVU UIFSF JT BOPUIFS XBZ UP NPOPJEBMMZ DPNCJOF MJTUT
8IFSFBT UIF EFGBVMU -JTU NBQQFOE FOET VQ EPJOH UIF GPMMPX
JOH

[1, 2, 3] <> [4, 5, 6]

-- changes to

[1, 2, 3] ++ [4, 5, 6]

[1, 2, 3, 4, 5, 6]

5IF ;JQ-JTU NPOPJE DPNCJOFT UIF WBMVFT PG UIF UXP MJTUT


BT QBSBMMFM TFRVFODFT VTJOH B NPOPJE QSPWJEFE CZ UIF WBMVFT
UIFNTFMWFT UP HFU UIF KPC EPOF
$)"15&3  "11-*$"5*7& 

[1, 2, 3] <> [4, 5, 6]

-- changes to

[
1 <> 4
, 2 <> 5
, 3 <> 6
]

5IJT TIPVME SFNJOE ZPV PG GVODUJPOT MJLF zip BOE zipWith


5P NBLF UIF BCPWF FYBNQMF XPSL ZPV DBO BTTFSU B UZQF MJLF
Sum Integer GPS UIF /VN WBMVFT UP HFU B .POPJE

Prelude> import Data.Monoid


Prelude> 1 <> 2

No instance for (Num a0) arising from a use of ‘it’


The type variable ‘a0’ is ambiguous
Note: there are several potential instances:
... some blather that mentions Num ...

Prelude> 1 <> (2 :: Sum Integer)


Sum {getSum = 3}

1SFMVEF EPFTOƊU QSPWJEF UIJT .POPJE GPS VT TP XF NVTU


EFƶOF JU PVSTFMWFT
$)"15&3  "11-*$"5*7& 

module Apl1 where

import Control.Applicative
import Data.Monoid
import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes

-- unfortunate orphan instances. Try to avoid these


-- in code you're going to keep or release.

-- this isn't going to work properly


instance Monoid a => Monoid (ZipList a) where
mempty = ZipList []
mappend = liftA2 mappend

instance Arbitrary a => Arbitrary (ZipList a) where


arbitrary = ZipList <$> arbitrary

instance Arbitrary a => Arbitrary (Sum a) where


arbitrary = Sum <$> arbitrary

instance Eq a => EqProp (ZipList a) where (=-=) = eq

*G XF ƶSF UIJT VQ JO UIF 3&1- BOE UFTU GPS JUT WBMJEJUZ BT B


.POPJE JUƊMM GBJM
$)"15&3  "11-*$"5*7& 

Prelude> quickBatch $ monoid (ZipList [1 :: Sum Int])

monoid:
left identity: *** Failed! Falsifiable (after 3 tests):
ZipList [ Sum {getSum = -1} ]
right identity: *** Failed! Falsifiable (after 4 tests):
ZipList [ Sum {getSum = -1}
, Sum {getSum = 3}
, Sum {getSum = 2} ]
associativity: +++ OK, passed 500 tests.

5IF QSPCMFN JT UIBU UIF FNQUZ ;JQ-JTU JT UIF [FSP BOE OPU
UIF JEFOUJUZ

;FSP WT *EFOUJUZ


-- Zero
n * 0 == 0

-- Identity
n * 1 == n

4P IPX EP XF HFU BO JEFOUJUZ GPS ;JQ-JTU

Sum 1 `mappend` ??? -> Sum 1


$)"15&3  "11-*$"5*7& 

instance Monoid a => Monoid (ZipList a) where


mempty = pure mempty
mappend = liftA2 mappend

:PVƊMM ƶOE PVU XIBU UIF ƌQVSFƍ EPFT IFSF XIFO ZPV XSJUF
UIF "QQMJDBUJWF GPS ;JQ-JTU ZPVSTFMG

-JTU "QQMJDBUJWF &YFSDJTF


*NQMFNFOU UIF -JTU "QQMJDBUJWF 8SJUJOH B NJOJNBMMZ DPNQMFUF
"QQMJDBUJWF JOTUBODF DBMMT GPS XSJUJOH UIF EFƶOJUJPOT PG CPUI
pure BOE <*> 8FƊSF HPJOH UP QSPWJEF B IJOU BT XFMM 6TF UIF
DIFDLFST MJCSBSZ UP WBMJEBUF ZPVS "QQMJDBUJWF JOTUBODF

data List a =
Nil
| Cons a (List a)
deriving (Eq, Show)

3FNFNCFS XIBU ZPV XSPUF GPS UIF -JTU 'VODUPS

instance Functor List where


fmap = undefined

8SJUJOH UIF -JTU "QQMJDBUJWF JT TJNJMBS

instance Applicative List where


pure = undefined
(<*>) = undefined
$)"15&3  "11-*$"5*7& 

&YQFDUFE SFTVMU

Prelude> let functions = Cons (+1) (Cons (*2) Nil)


Prelude> let values = Cons 1 (Cons 2 Nil)
Prelude> functions <*> values
Cons 2 (Cons 3 (Cons 2 (Cons 4 Nil)))

*O DBTF ZPV HFU TUVDL VTF UIF GPMMPXJOH GVODUJPOT BOE IJOUT

append :: List a -> List a -> List a


append Nil ys = ys
append (Cons x xs) ys = Cons x $ xs `append` ys

fold :: (a -> b -> b) -> b -> List a -> b


fold _ b Nil = b
fold f b (Cons h t) = f h (fold f b t)

concat' :: List (List a) -> List a


concat' = fold append Nil

-- write this one in terms of concat' and fmap


flatMap :: (a -> List b) -> List a -> List b
flatMap f as = undefined

6TF UIF BCPWF BOE USZ VTJOH ƷBU.BQ BOE GNBQ XJUIPVU
FYQMJDJUMZ QBUUFSONBUDIJOH PO $POT DFMMT :PVƊMM TUJMM OFFE UP
IBOEMF UIF /JM DBTFT
$)"15&3  "11-*$"5*7& 

flatMap JT MFTT TUSBOHF UIBO JU XPVME JOJUJBMMZ TFFN *UƊT CBTJ


DBMMZ ƌGNBQ UIFO TNVTIƍ

Prelude> fmap (\x -> [x, 9]) [1, 2, 3]


[[1,9],[2,9],[3,9]]

Prelude> let toMyList = foldr Cons Nil


Prelude> let xs = toMyList [1, 2, 3]
Prelude> let c = Cons

Prelude> flatMap (\x -> x `c` (9 `c` Nil)) xs


Cons 1 (Cons 9 (Cons 2
(Cons 9 (Cons 3 (Cons 9 Nil)))))

"QQMJDBUJWF JOTUBODFT VOMJLF 'VODUPST BSF OPU HVBSBOUFFE


UP IBWF B VOJRVF JNQMFNFOUBUJPO GPS B HJWFO EBUBUZQF

;JQ-JTU "QQMJDBUJWF &YFSDJTF

*NQMFNFOU UIF ;JQ-JTU "QQMJDBUJWF 6TF UIF DIFDLFST MJCSBSZ UP


WBMJEBUF ZPVS "QQMJDBUJWF JOTUBODF 8FƊSF HPJOH UP QSPWJEF UIF
&R1SPQ JOTUBODF BOE FYQMBJO UIF XFJSEOFTT JO B NPNFOU
$)"15&3  "11-*$"5*7& 

data List a =
Nil
| Cons a (List a)
deriving (Eq, Show)

take' :: Int -> List a -> List a


take' = undefined

instance Functor List where


fmap = undefined

instance Applicative List where


pure = undefined
(<*>) = undefined

newtype ZipList' a =
ZipList' (List a)
deriving (Eq, Show)

instance Eq a => EqProp (ZipList' a) where


xs =-= ys = xs' `eq` ys'
where xs' = let (ZipList' l) = xs
in take' 3000 l
ys' = let (ZipList' l) = ys
in take' 3000 l
$)"15&3  "11-*$"5*7& 

instance Functor ZipList' where


fmap f (ZipList' xs) = ZipList' $ fmap f xs

instance Applicative ZipList' where


pure = undefined
(<*>) = undefined

5IF JEFB JT UP BMJHO B MJTU PG GVODUJPOT XJUI B MJTU PG WBMVFT


BOE BQQMZ UIF ƶSTU GVODUJPO UP UIF ƶSTU WBMVF BOE TP PO 5IF
JOTUBODF TIPVME XPSL XJUI JOƶOJUF MJTUT 4PNF FYBNQMFT

Prelude> let z = ZipList' [(+9), (*2), (+8)]


Prelude> let z' = ZipList' [1..3]
Prelude> z <*> z'
ZipList' [10,4,11]
Prelude> let z' = ZipList' (repeat 1)
Prelude> z <*> z'
ZipList' [10,2,9]

/PUF UIBU UIF TFDPOE z' XBT BO JOƶOJUF MJTU $IFDL 1SFMVEF
GPS GVODUJPOT UIBU DBO HJWF ZPV XIBU ZPV OFFE 0OF TUBSUT
XJUI UIF MFUUFS [ UIF PUIFS XJUI UIF MFUUFS S :PVƊSF MPPLJOH
GPS JOTQJSBUJPO GSPN UIFTF GVODUJPOT OPU UP CF BCMF UP EJSFDUMZ
SFVTF UIFN BT ZPVƊSF VTJOH B DVTUPN -JTU UZQF BOE OPU UIF
QSPWJEFE 1SFMVEF MJTU UZQF
$)"15&3  "11-*$"5*7& 

&YQMBJOJOH BOE KVTUJGZJOH UIF XFJSE &R1SPQ 5IF HPPE OFXT


JT JUƊT EqProp UIBU IBT UIF XFJSE ƌDIFDL POMZ UIF ƶSTU   WBM
VFTƍ TFNBOUJDT JOTUFBE PG NBLJOH UIF &R JOTUBODF XFJSE 5IF
CBE OFXT JT UIJT JT B CZQSPEVDU PG UFTUJOH GPS FRVBMJUZ CFUXFFO
JOƶOJUF MJTUTƒUIBU JT ZPV DBOƊU *G ZPV VTF B UZQJDBM EqProp JO
TUBODF UIF UFTU GPS IPNPNPSQIJTN JO ZPVS "QQMJDBUJWF JO
TUBODF XJMM DIBTF UIF JOƶOJUF MJTUT GPSFWFS 4JODF 2VJDL$IFDL
JT BMSFBEZ BO FYFSDJTF JO ƌHPPE FOPVHIƍ WBMJEJUZ DIFDLJOH XF
DPVME DIPPTF UP GFFM KVTUJƶFE JO UIJT *G ZPV EPOƊU CFMJFWF VT USZ
SVOOJOH UIF GPMMPXJOH JO ZPVS 3&1-

repeat 1 == repeat 1

&JUIFS BOE 7BMJEBUJPO "QQMJDBUJWF


:FQ IFSF XF HP BHBJO XJUI UIF UZQFT

4QFDJBMJ[JOH UIF UZQFT

-- f ~ Either e

(<*>) :: f (a -> b) -> f a -> f b


(<*>) :: Either e (a -> b) -> Either e a -> Either e b

pure :: a -> f a
pure :: a -> Either e a
$)"15&3  "11-*$"5*7& 

&JUIFS WFSTVT 7BMJEBUJPO


0ǒFO UIF JOUFSFTUJOH QBSU PG BO "QQMJDBUJWF JT XIFSFWFS UIF
ƌNPOPJEBMƍ JO ƌNPOPJEBM GVODUPSƍ JT DPNJOH GSPN 0OF CZQSPE
VDU PG UIJT JT UIBU KVTU BT ZPV DBO IBWF NPSF UIBO POF WBMJE
.POPJE GPS B HJWFO EBUBUZQF VOMJLF 'VODUPS "QQMJDBUJWF DBO
IBWF NPSF UIBO POF WBMJE BOE MBXGVM JOTUBODF GPS B HJWFO
EBUBUZQF
5IF GPMMPXJOH JT B CSJFG EFNPOTUSBUJPO PG &JUIFS

Prelude> pure 1 :: Either e Int


Right 1

Prelude> Right (+1) <*> Right 1


Right 2
Prelude> Right (+1) <*> Left ":("
Left ":("
Prelude> Left ":(" <*> Right 1
Left ":("
Prelude> Left ":(" <*> Left "sadface.png"
Left ":("

8FƊWF DPWFSFE UIF CFOFƶUT PG &JUIFS BMSFBEZ BOE XFƊWF


TIPXO ZPV XIBU UIF .BZCF "QQMJDBUJWF DBO DMFBO VQ TP XF
XPOƊU CFMBCPS UIPTF QPJOUT 5IFSFƊT BO BMUFSOBUJWF UP &JUIFS
UIBU EJƵFST POMZ JO UIF "QQMJDBUJWF JOTUBODF DBMMFE 7BMJEBUJPO
$)"15&3  "11-*$"5*7& 

data Validation err a =


Failure err
| Success a
deriving (Eq, Show)

0OF UIJOH UP SFBMJ[F JT UIBU UIJT JT JEFOUJDBM UP UIF &JUIFS


EBUBUZQF BOE UIFSF JT FWFO B QBJS PG UPUBM GVODUJPOT XIJDI DBO
HP CFUXFFO 7BMJEBUJPO BOE &JUIFS WBMVFT JOUFSDIBOHFBCMZ

-- Remember when we mentioned natural transformations?


-- Both of these functions are natural transformations.

validToEither :: Validation e a -> Either e a


validToEither (Failure err) = Left err
validToEither (Success a) = Right a

eitherToValid :: Either e a -> Validation e a


eitherToValid (Left err) = Failure err
eitherToValid (Right a) = Success a

eitherToValid . validToEither == id
validToEither . eitherToValid == id

)PX EPFT 7BMJEBUJPO EJƵFS 1SJODJQBMMZ JO XIBU UIF "QQMJDB


UJWF JOTUBODF EPFT XJUI FSSPST 3BUIFS UIBO KVTU TIPSUDJSDVJUJOH
XIFO JU IBT UXP FSSPS WBMVFT JUƊMM VTF UIF .POPJE UZQFDMBTT UP
$)"15&3  "11-*$"5*7& 

DPNCJOF UIFN 0ǒFO UIJTƊMM KVTU CF B MJTU PS TFU PG FSSPST CVU


ZPV DBO EP XIBUFWFS ZPV XBOU

data Errors =
DividedByZero
| StackOverflow
| MooglesChewedWires
deriving (Eq, Show)

success = Success (+1)


<*> Success 1

success == Success 2

failure = Success (+1)


<*> Failure [StackOverflow]

failure == Failure [StackOverflow]

failure' = Failure [StackOverflow]


<*> Success (+1)

failure' == Failure [StackOverflow]


$)"15&3  "11-*$"5*7& 

failures =
Failure [MooglesChewedWires]
<*> Failure [StackOverflow]

failures ==
Failure [MooglesChewedWires
, StackOverflow]

8JUI UIF WBMVF failures XF TFF XIBU EJTUJOHVJTIFT &JUIFS


BOE 7BMJEBUJPO XF DBO OPX QSFTFSWF BMM GBJMVSFT UIBU PDDVSSFE
OPU KVTU UIF ƶSTU POF

&YFSDJTF 7BSJBUJPOT PO &JUIFS

7BMJEBUJPO IBT UIF TBNF SFQSFTFOUBUJPO BT &JUIFS CVU JU DBO CF


EJƵFSFOU 5IF Functor XJMM CFIBWF UIF TBNF CVU UIF Applicative
XJMM CF EJƵFSFOU 4FF BCPWF GPS BO JEFB PG IPX 7BMJEBUJPO
TIPVME CFIBWF 6TF UIF DIFDLFST MJCSBSZ

data Validation e a =
Failure e
| Success a
deriving (Eq, Show)
$)"15&3  "11-*$"5*7& 

-- same as Either
instance Functor (Validation e) where
fmap = undefined

-- This is different
instance Monoid e =>
Applicative (Validation e) where
pure = undefined
(<*>) = undefined

 $IBQUFS &YFSDJTFT


(JWFO B UZQF UIBU IBT BO JOTUBODF PG "QQMJDBUJWF TQFDJBMJ[F UIF
UZQFT PG UIF NFUIPET 5FTU ZPVS TQFDJBMJ[BUJPO JO UIF 3&1-
0OF XBZ UP EP UIJT JT UP CJOE BMJBTFT PG UIF UZQFDMBTT NFUIPET
UP ƌNPSF DPODSFUFƍ UZQFT UIBU IBWF UIF UZQF XF UPME ZPV UP ƶMM
JO

 -- Type
[]

-- Methods
pure :: a -> ? a
(<*>) :: ? (a -> b) -> ? a -> ? b
$)"15&3  "11-*$"5*7& 

 -- Type
IO

-- Methods
pure :: a -> ? a
(<*>) :: ? (a -> b) -> ? a -> ? b

 -- Type
(,) a

-- Methods
pure :: a -> ? a
(<*>) :: ? (a -> b) -> ? a -> ? b

 -- Type
(->) e

-- Methods
pure :: a -> ? a
(<*>) :: ? (a -> b) -> ? a -> ? b

8SJUF BQQMJDBUJWF JOTUBODFT GPS UIF GPMMPXJOH EBUBUZQFT $PO


GVTFE 8SJUF PVU XIBU UIF UZQF TIPVME CF 6TF UIF DIFDLFST
MJCSBSZ UP WBMJEBUF UIF JOTUBODFT

 data Pair a = Pair a a deriving Show


$)"15&3  "11-*$"5*7& 

 5IJT TIPVME MPPL GBNJMJBS

data Two a b = Two a b

 data Three a b c = Three a b c

 data Three' a b = Three' a b b

 data Four a b c d = Four a b c d

 data Four' a b = Four' a a a b

$PNCJOBUJPOT
3FNFNCFS UIF WPXFMT BOE TUPQT DIBQUFS FYFSDJTF JO GPMET
8SJUF UIF GVODUJPO UP HFOFSBUF UIF QPTTJCMF DPNCJOBUJPOT PG
UISFF JOQVU MJTUT VTJOH liftA3 GSPN $POUSPM"QQMJDBUJWF

import Control.Applicative (liftA3)

stops :: String
stops = "pbtdkg"

vowels :: String
vowels = "aeiou"

combos :: [a] -> [b] -> [c] -> [(a, b, c)]


combos = undefined
$)"15&3  "11-*$"5*7& 

 %FƶOJUJPOT
 "QQMJDBUJWF JT B UZQFDMBTT JO )BTLFMM XIJDI ZPV DPVME UIJOL
PG BT UIF +POBUIBO 5BZMPS 5IPNBT UP 'VODUPS BOE .POBEƊT
5BSBO /PBI 4NJUI BOE ;BDIFSZ 5Z #SZBO "QQMJDBUJWF DBO
CF UIPVHIU PG DIBSBDUFSJ[JOH NPOPJEBM GVODUPST JO )BTLFMM
'PS B )BTLFMMFSƊT QVSQPTFT JUƊT B XBZ UP GVODUPSJBMMZ BQQMZ
B GVODUJPO XIJDI JT FNCFEEFE JO TUSVDUVSF ԕ PG UIF TBNF
UZQF BT UIF WBMVF ZPVƊSF NBQQJOH JU PWFS

fmap :: (a -> b) -> f a -> f b

(<*>) :: f (a -> b) -> f a -> f b

 'PMMPXVQ SFTPVSDFT


 5POZ .PSSJT /JDL 1BSUSJEHF 7BMJEBUJPO MJCSBSZ
http://hackage.haskell.org/package/validation

 $POPS .D#SJEF 3PTT 1BUFSTPO "QQMJDBUJWF 1SPHSBNNJOH


XJUI &ƵFDUT
http://staff.city.ac.uk/~ross/papers/Applicative.html

 +FSFNZ (JCCPOT #SVOP $ E 4 0MJWFJSB &TTFODF PG UIF


*UFSBUPS 1BUUFSO

 3PTT 1BUFSTPO $POTUSVDUJOH "QQMJDBUJWF 'VODUPST


http://staff.city.ac.uk/~ross/papers/Constructors.html
$)"15&3  "11-*$"5*7& 

 4BN -JOEMFZ 1IJMJQ 8BEMFS +FSFNZ :BMMPQ *EJPNT BSF


PCMJWJPVT BSSPXT BSF NFUJDVMPVT NPOBET BSF QSPNJTDV
PVT

/PUF *EJPN NFBOT BQQMJDBUJWF GVODUPS BOE JT B VTFGVM


TFBSDI UFSN GPS QVCMJTIFE XPSL PO BQQMJDBUJWF GVODUPST
$IBQUFS 

.POBE

5IFSF JT OPUIJOH TP
QSBDUJDBM BT B HPPE UIFPSZ

1IJM 8BEMFS RVPUJOH ,VSU


-FXJO


$)"15&3  .0/"% 

 .POBE
'JOBMMZ XF DPNF UP POF PG UIF NPTU UBMLFE BCPVU TUSVDUVSFT JO
)BTLFMM UIF NPOBE .POBET BSF OPU TUSJDUMZ TQFBLJOH OFD
FTTBSZ UP )BTLFMM "MUIPVHI UIF DVSSFOU TUBOEBSE GPS )BTLFMM
EPFT VTF NPOBE GPS DPOTUSVDUJOH BOE USBOTGPSNJOH IO BDUJPOT
PMEFS JNQMFNFOUBUJPOT PG )BTLFMM EJE OPU .POBET BSF QPXFS
GVM BOE GVO CVU UIFZ EP OPU EFƶOF )BTLFMM 3BUIFS NPOBET
BSF EFƶOFE JO UFSNT PG )BTLFMM
.POBET BSF BQQMJDBUJWF GVODUPST CVU UIFZ IBWF TPNFUIJOH
TQFDJBM BCPVU UIFN UIBU NBLFT UIFN EJƵFSFOU GSPN BOE NPSF
QPXFSGVM UIBO FJUIFS <*> PS fmap BMPOF *O UIJT DIBQUFS XF

Ƒ EFƶOF Monad JUT PQFSBUJPOT BOE MBXT

Ƒ MPPL BU TFWFSBM FYBNQMFT PG NPOBET JO QSBDUJDF

Ƒ XSJUF UIF Monad JOTUBODFT GPS WBSJPVT UZQFT

Ƒ BEESFTT TPNF NJTJOGPSNBUJPO BCPVU NPOBET

 4PSSZ  .POBE JT OPU B CVSSJUP



8FMM UIFO XIBU UIF IFDL JT B NPOBE

4FDUJPO UJUMF XJUI BMM EVF SFTQFDU BOE HSBUJUVEF UP .BSL +BTPO %PNJOVT XIPTF
CMPH QPTU ƌ.POBET BSF MJLF CVSSJUPTƍ JT B DMBTTJD PG JUT HFOSF http://blog.plover.com/prog/
burritos.html
$)"15&3  .0/"% 

"T XF TBJE BCPWF B NPOBE JT BO BQQMJDBUJWF GVODUPS XJUI


TPNF VOJRVF GFBUVSFT UIBU NBLF JU B CJU NPSF QPXFSGVM UIBO
FJUIFS BMPOF " GVODUPS NBQT B GVODUJPO PWFS TPNF TUSVDUVSF
BO BQQMJDBUJWF NBQT B GVODUJPO UIBU JT DPOUBJOFE JO TPNF TUSVD
UVSF PWFS TPNF PUIFS TUSVDUVSF BOE UIFO DPNCJOFT UIF UXP
MBZFST PG TUSVDUVSF MJLF NBQQFOE 4P ZPV DBO UIJOL PG NPOBET
BT KVTU BOPUIFS XBZ PG BQQMZJOH GVODUJPOT PWFS TUSVDUVSF XJUI
B DPVQMF PG BEEJUJPOBM GFBUVSFT 8FƊMM HFU UP UIPTF GFBUVSFT JO B
NPNFOU 'PS OPX MFUƊT DIFDL PVU UIF UZQFDMBTT EFƶOJUJPO BOE
DPSF PQFSBUJPOT
*G ZPV BSF VTJOH ()$  PS OFXFS ZPVƊMM TFF BO Applicative
DPOTUSBJOU JO UIF EFƶOJUJPO PG .POBE BT JU TIPVME CF

class Applicative m => Monad m where


(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a

8FƊSF HPJOH UP FYQMPSF UIJT JO TPNF EFUBJM -FUƊT TUBSU XJUI


UIF UZQFDMBTT DPOTUSBJOU PO m

"QQMJDBUJWF N
0MEFS WFSTJPOT PG ()$ EJE OPU IBWF "QQMJDBUJWF BT B TVQFSDMBTT
PG .POBE (JWFO UIBU .POBE JT TUSPOHFS UIBO "QQMJDBUJWF BOE
"QQMJDBUJWF JT TUSPOHFS UIBO 'VODUPS ZPV DBO EFSJWF "QQMJDB
UJWF BOE 'VODUPS JO UFSNT PG .POBE KVTU BT ZPV DBO EFSJWF
$)"15&3  .0/"% 

'VODUPS JO UFSNT PG "QQMJDBUJWF 8IBU EPFT UIJT NFBO *U


NFBOT ZPV DBO XSJUF fmap VTJOH NPOBEJD PQFSBUJPOT BOE JU
XPSLT KVTU ƶOF

fmap f xs = xs >>= return . f

5SZ JU GPS ZPVSTFMG

Prelude> fmap (+1) [1..3]


[2,3,4]

Prelude> [1..3] >>= return . (+1)


[2,3,4]

5IJT IBQQFOT UP CF B MBX OPU KVTU B DPOWFOJFODF Functor


Applicative BOE Monad JOTUBODFT GPS B HJWFO UZQF TIPVME IBWF
UIF TBNF DPSF CFIBWJPS
8FƊMM FYQMPSF UIF SFMBUJPOTIJQ CFUXFFO UIFTF DMBTTFT NPSF
DPNQMFUFMZ JO KVTU B CJU CVU BT QBSU PG VOEFSTUBOEJOH UIF UZQF
DMBTT EFƶOJUJPO BCPWF JUƊT JNQPSUBOU UP VOEFSTUBOE UIJT DIBJO
PG EFQFOEFODZ

Functor -> Applicative -> Monad

8IFOFWFS ZPVƊWF JNQMFNFOUFE BO JOTUBODF PG Monad GPS B


UZQF ZPV OFDFTTBSJMZ IBWF BO "QQMJDBUJWF BOE B Functor BT XFMM
$)"15&3  .0/"% 

$PSF PQFSBUJPOT
5IF Monad UZQFDMBTT EFƶOFT UISFF DPSF PQFSBUJPOT BMUIPVHI
ZPV POMZ OFFE UP EFƶOF >>= GPS B NJOJNBMMZ DPNQMFUF Monad
JOTUBODF -FUƊT MPPL BU BMM UISFF

(>>=) :: m a -> (a -> m b) -> m b


(>>) :: m a -> m b -> m b
return :: a -> m a

8F DBO EJTQFOTF XJUI UIF MBTU PG UIPTF return QSFUUZ FBTJMZ


JUƊT KVTU UIF TBNF BT pure "MM JU EPFT JT UBLF B WBMVF BOE SFUVSO JU
JOTJEF ZPVS TUSVDUVSF XIFUIFS UIBU TUSVDUVSF JT B MJTU PS Just PS
IO 8F UBMLFE BCPVU JU B CJU BOE VTFE JU CBDL JO UIF .PEVMFT
DIBQUFS BOE XF DPWFSFE pure JO UIF "QQMJDBUJWF DIBQUFS TP
UIFSF JTOƊU NVDI FMTF UP TBZ BCPVU JU
5IF OFYU PQFSBUPS >> EPFTOƊU IBWF BO PƸDJBM &OHMJTIMBOHVBHF
OBNF CVU XF MJLF UP DBMM JU .S 1PJOUZ 4PNF QFPQMF EP SFGFS
UP JU BT UIF TFRVFODJOH PQFSBUPS XIJDI XF NVTU BENJU JT NPSF
JOGPSNBUJWF UIBO .S 1PJOUZ #BTJDBMMZ .S 1PJOUZ TFRVFODFT
UXP BDUJPOT XIJMF EJTDBSEJOH BOZ SFTVMUJOH WBMVF PG UIF ƶSTU
BDUJPO Applicative IBT B TJNJMBS PQFSBUPS BT XFMM BMUIPVHI XF
EJEOƊU UBML BCPVU JU JO UIBU DIBQUFS 8F XJMM TFF FYBNQMFT PG
UIJT PQFSBUPS JO UIF VQDPNJOH TFDUJPO PO do TZOUBY
'JOBMMZ UIF CJH bind 5IF >>= PQFSBUPS JT DBMMFE CJOE BOE
JT ƈ PS BU MFBTU DPOUBJOT ƈ UIF UIJOHT UIBU BSF TQFDJBM BCPVU
Monad
$)"15&3  .0/"% 

5IF OPWFM QBSU PG .POBE


$POWFOUJPOBMMZ XIFO XF VTF NPOBET XF VTF UIF CJOE GVODUJPO
>>= 4PNFUJNFT XF VTF JU EJSFDUMZ TPNFUJNFT JOEJSFDUMZ WJB do
TZOUBY 5IF RVFTUJPO XF TIPVME BTL PVSTFMWFT JT XIBUƊT VOJRVF
UP .POBE ƈ BU MFBTU GSPN UIF QPJOU PG WJFX PG UZQFT
8F BMSFBEZ TBX UIBU JUƊT OPU return UIBUƊT KVTU BOPUIFS OBNF
GPS pure GSPN Applicative
8F BMTP OPUFE BOE XJMM TFF NPSF DMFBSMZ TPPO
UIBU JU BMTP
JTOƊU >> XIJDI IBT B DPVOUFSQBSU JO Applicative
"OE JU BMTP JTOƊU >>= BU MFBTU OPU JO JUT FOUJSFUZ 5IF UZQF PG
>>= JT WJTJCMZ TJNJMBS UP UIBU PG fmap BOE <*> XIJDI NBLFT TFOTF
TJODF NPOBET BSF BQQMJDBUJWF GVODUPST 'PS UIF TBLF PG NBLJOH
UIJT NBYJNBMMZ TJNJMBS XFƊSF HPJOH UP DIBOHF UIF Ԝ PG Monad
UP ԕ

fmap :: Functor f => (a -> b) -> f a -> f b


<*> :: Applicative f => f (a -> b) -> f a -> f b
>>= :: Monad f => f a -> (a -> f b) -> f b

0, TP CJOE JT RVJUF TJNJMBS UP <*> BOE fmap CVU XJUI UIF ƶSTU
UXP BSHVNFOUT ƷJQQFE 4UJMM UIF JEFB PG NBQQJOH B GVODUJPO
PWFS B WBMVF XIJMF CZQBTTJOH JUT TVSSPVOEJOH TUSVDUVSF JT OPU
VOJRVF UP Monad
8F DBO EFNPOTUSBUF UIJT CZ GNBQQJOH B GVODUJPO PG UZQF (a
-> m b) UP NBLF JU NPSF MJLF >>= BOE JU XJMM XPSL KVTU ƶOF /PUI
$)"15&3  .0/"% 

JOH XJMM TUPQ VT 8F XJMM DPOUJOVF VTJOH UIF UJMEF UP SFQSFTFOU
SPVHI FRVJWBMFODF CFUXFFO UXP UIJOHT

-- If b == f b

fmap :: Functor f => (a -> f b) -> f a -> f (f b)

-FUƊT EFNPOTUSBUF UIJT JEFB XJUI MJTU BT PVS TUSVDUVSF

Prelude> let andOne x = [x, 1]


Prelude> andOne 10
[10,1]

Prelude> :t fmap andOne [4, 5, 6]


fmap andOne [4, 5, 6] :: Num t => [[t]]

Prelude> fmap andOne [4, 5, 6]


[[4,1],[5,1],[6,1]]

#VU MP 8F LOFX GSPN PVS UZQFT UIBU XFƊE FOE VQ XJUI BO
f (f b) ƈ UIBU JT BO FYUSB MBZFS PG TUSVDUVSF BOE OPX XF IBWF
B SFTVMU PG OFTUFE MJTUT 8IBU JG XF KVTU XBOUFE Num a => [a]
JOTUFBE PG OFTUFE MJTUT 8F XBOU B TJOHMF MBZFS PG ԕ TUSVDUVSF
CVU PVS NBQQFE GVODUJPO IBT JUTFMG HFOFSBUFE NPSF TUSVDUVSF
"ǒFS NBQQJOH B GVODUJPO UIBU HFOFSBUFT BEEJUJPOBM NPOBEJD
TUSVDUVSF JO JUT SFUVSO UZQF XF XBOU B XBZ UP EJTDBSE POF MBZFS
PG UIBU TUSVDUVSF
$)"15&3  .0/"% 

4P IPX EP XF BDDPNQMJTI UIBU 8FMM XF TBX IPX UP EP


XIBU XF XBOU XJUI MJTUT WFSZ FBSMZ PO JO UIJT CPPL

Prelude> concat $ fmap andOne [4, 5, 6]


[4,1,5,1,6,1]

5IF UZQF PG concat GVMMZ HFOFSBMJ[FE

concat :: Foldable t => t [a] -> [a]

-- we can assert a less general type for our purposes here

concat :: [[a]] -> [a]

Monad JO B TFOTF JT B HFOFSBMJ[BUJPO PG DPODBU 5IF VOJRVF


QBSU PG Monad JT UIF GPMMPXJOH GVODUJPO

import Control.Monad (join)

join :: Monad m => m (m a) -> m a

-- compare

concat :: [[a]] -> [a]

*UƊT BMTP TPNFXIBU OPWFM UIBU XF DBO JOKFDU NPSF TUSVDUVSF


WJB PVS GVODUJPO BQQMJDBUJPO XIFSF BQQMJDBUJWFT BOE GNBQT
$)"15&3  .0/"% 

IBWF UP MFBWF UIF TUSVDUVSF VOUPVDIFE "MMPXJOH UIF GVODUJPO


JUTFMG UP BMUFS UIF TUSVDUVSF JT TPNFUIJOH XFƊWF OPU TFFO JO
Functor BOE Applicative BOE XFƊMM FYQMPSF UIF SBNJƶDBUJPOT PG
UIBU BCJMJUZ NPSF FTQFDJBMMZ XIFO XF TUBSU UBMLJOH BCPVU UIF
Maybe NPOBE #VU XF DBO JOKFDU NPSF TUSVDUVSF XJUI B TUBOEBSE
fmap JG XF XJTI BT XF TBX BCPWF )PXFWFS UIF BCJMJUZ UP ƷBUUFO
UIPTF UXP MBZFST PG TUSVDUVSF JOUP POF JT XIBU USVMZ NBLFT Monad
TQFDJBM "OE JUƊT CZ QVUUJOH UIBU join GVODUJPO UPHFUIFS XJUI
UIF NBQQJOH GVODUJPO UIBU XF HFU bind BMTP LOPXO BT >>=
4P IPX EP XF HFU CJOE

5IF BOTXFS JT UIF FYFSDJTF 8SJUF bind JO UFSNT PG fmap BOE


join
'FBS JT UIF NJOELJMMFS GSJFOE :PV DBO EP JU

-- keep in mind this is (>>=) flipped


bind :: Monad m => (a -> m b) -> m a -> m b
bind = undefined

8IBU .POBE JT OPU


4JODF Monad JT TPNFXIBU BCTUSBDU BOE DBO CF RVJUF TMJQQFSZ
NBOZ QFPQMF UBML BCPVU JU GSPN POF PS UXP QFSTQFDUJWFT UIBU
UIFZ GFFM NPTU DPNGPSUBCMF XJUI 2VJUF PǒFO UIFZ BEESFTT
XIBU Monad JT GSPN UIF QFSTQFDUJWF PG UIF IO Monad IO EPFT
IBWF B Monad JOTUBODF BOE JU JT B WFSZ DPNNPO VTF PG NPOBET
$)"15&3  .0/"% 

)PXFWFS VOEFSTUBOEJOH NPOBET POMZ UISPVHI UIBU JOTUBODF


MFBET UP MJNJUFE JOUVJUJPOT GPS XIBU NPOBET BSF BOE DBO EP
BOE UP B MFTTFS FYUFOU B XSPOH OPUJPO PG XIBU IO JT BMM BCPVU
.POBE JT OPU

 *NQVSF .POBEJD GVODUJPOT BSF QVSF GVODUJPOT IO JT BO BC


TUSBDU EBUBUZQF UIBU BMMPXT GPS JNQVSF PS FƵFDUGVM BDUJPOT
BOE JU IBT B Monad JOTUBODF #VU UIFSFƊT OPUIJOH JNQVSF
BCPVU NPOBET

 "O FNCFEEFE MBOHVBHF GPS JNQFSBUJWF QSPHSBNNJOH 4J


NPO 1FZUPO+POFT POF PG UIF MFBE EFWFMPQFST BOE SF
TFBSDIFST PG )BTLFMM BOE JUT JNQMFNFOUBUJPO JO ()$ IBT
GBNPVTMZ TBJE ƌ)BTLFMM JT UIF XPSMEƊT ƶOFTU JNQFSBUJWF
QSPHSBNNJOH MBOHVBHF ƍ BOE IF XBT UBMLJOH BCPVU UIF
XBZ NPOBET IBOEMF FƵFDUGVM QSPHSBNNJOH 8IJMF NPO
BET BSF PǒFO VTFE GPS TFRVFODJOH BDUJPOT JO B XBZ UIBU
MPPLT MJLF JNQFSBUJWF QSPHSBNNJOH UIFSF BSF DPNNVUB
UJWF NPOBET UIBU EP OPU PSEFS BDUJPOT 8FƊMM TFF POF B GFX
DIBQUFST EPXO UIF MJOF XIFO XF UBML BCPVU Reader

 " WBMVF 5IF UZQFDMBTT EFTDSJCFT B TQFDJƶD SFMBUJPOTIJQ CF


UXFFO FMFNFOUT JO B EPNBJO BOE EFƶOFT TPNF PQFSBUJPOT
PWFS UIFN 8IFO XF SFGFS UP TPNFUIJOH BT ƌB NPOBE ƍ
XFƊSF VTJOH UIBU UIF TBNF XBZ XF UBML BCPVU ƌB NPOPJE ƍ
PS ƌB GVODUPSƍ /POF PG UIPTF BSF WBMVFT
$)"15&3  .0/"% 

 "CPVU TUSJDUOFTT 5IF NPOBEJD PQFSBUJPOT PG bind BOE


return BSF OPOTUSJDU 4PNF PQFSBUJPOT DBO CF NBEF TUSJDU
XJUIJO B TQFDJƶD JOTUBODF 8FƊMM UBML NPSF BCPVU UIJT MBUFS
JO UIF CPPL

6TJOH NPOBET BMTP EPFTOƊU SFRVJSF LOPXJOH NBUI 0S DBUF


HPSZ UIFPSZ *U EPFT OPU SFRVJSF NZTUJDBM USJQT UP UIF UPQT PG
NPVOUBJOT PS TUBSWJOH POFTFMG JO B EFTFSU TPNFXIFSF
5IF Monad UZQFDMBTT JT HFOFSBMJ[FE TUSVDUVSF NBOJQVMBUJPO
XJUI TPNF MBXT UP NBLF JU TFOTJCMF +VTU MJLF Functor BOE Applicative
8F TPSU PG IBUF UP EJNJOJTI UIF NZTUJRVF CVU UIBUƊT SFBMMZ BMM
UIFSF JT UP JU

.POBE BMTP MJǒT


5IF Monad DMBTT BMTP JODMVEFT B TFU PG lift GVODUJPOT UIBU BSF UIF
TBNF BT UIF POFT XF BMSFBEZ TBX JO Applicative 5IFZ EPOƊU
SFBMMZ EP BOZUIJOH EJƵFSFOU CVU UIFZ BSF TUJMM BSPVOE CFDBVTF
TPNF MJCSBSJFT VTFE UIFN CFGPSF BQQMJDBUJWFT XFSF EJTDPWFSFE
TP UIF liftM TFU PG GVODUJPOT TUJMM FYJTUT UP NBJOUBJO DPNQBUJCJM
JUZ 4P ZPV NBZ TUJMM TFF UIFN TPNFUJNFT 8FƊMM UBLF B TIPSU
UPVS PG UIFN DPNQBSJOH UIFN EJSFDUMZ UP UIFJS BQQMJDBUJWF
DPVOUFSQBSUT

liftA :: Applicative f => (a -> b) -> f a -> f b


liftM :: Monad m => (a1 -> r) -> m a1 -> m r
$)"15&3  .0/"% 

"T ZPV NBZ SFDBMM UIBU JT KVTU fmap XJUI B EJƵFSFOU UZQFDMBTT
DPOTUSBJOU *G ZPVƊE MJLF UP TFF FYBNQMFT PG IPX JU XPSLT XF
FODPVSBHF ZPV UP XSJUF fmap GVODUJPOT JO ZPVS 3&1- BOE UBLF
UVSOT SFQMBDJOH UIF fmap XJUI liftA PS liftM
#VU UIBUƊT OPU BMM XF IBWF

liftA2 :: Applicative f =>


(a -> b -> c)
-> f a
-> f b
-> f c

liftM2 :: Monad m =>


(a1 -> a2 -> r)
-> m a1
-> m a2
-> m r

"TJEF GSPN UIF OVNCFSJOH UIFTF BQQFBS UIF TBNF -FUƊT USZ
UIFN PVU

Prelude> liftA2 (,) (Just 3) (Just 5)


Just (3,5)

Prelude> liftM2 (,) (Just 3) (Just 5)


Just (3,5)
$)"15&3  .0/"% 

:PV NBZ SFNFNCFS XBZ CBDL JO -JTUT XF UBMLFE BCPVU B


GVODUJPO DBMMFE zipWith zipWith JT liftA2 PS liftM2 TQFDJBMJ[FE
UP MJTUT

Prelude> :t zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
Prelude> zipWith (+) [3, 4] [5, 6]
[8,10]
Prelude> liftA2 (+) [3, 4] [5, 6]
[8,9,9,10]

8FMM UIF UZQFT BSF UIF TBNF CVU UIF CFIBWJPS EJƵFST 5IF
EJƵFSJOH CFIBWJPS IBT UP EP XJUI XIJDI MJTU NPOPJE JT CFJOH
VTFE
"MM SJHIU 5IFO XF IBWF UIF UISFFT

liftA3 :: Applicative f =>


(a -> b -> c -> d)
-> f a -> f b
-> f c -> f d
liftM3 :: Monad m =>
(a1 -> a2 -> a3 -> r)
-> m a1 -> m a2
-> m a3 -> m r

"OE DPJODJEFOUBMMZ UIFSF JT BMTP B zipWith3 GVODUJPO -FUƊT


TFF XIBU IBQQFOT
$)"15&3  .0/"% 

Prelude> :t zipWith3
zipWith3 :: (a -> b -> c -> d) ->
[a] -> [b] -> [c] -> [d]

Prelude> liftM3 (,,) [1, 2] [3] [5, 6]


[(1,3,5),(1,3,6),(2,3,5),(2,3,6)]
Prelude> zipWith3 (,,) [1, 2] [3] [5, 6]
[(1,3,5)]

"HBJO VTJOH B EJƵFSFOU NPOPJE HJWFT VT B EJƵFSFOU TFU PG


SFTVMUT
8F XBOUFE UP JOUSPEVDF UIFTF GVODUJPOT IFSF CFDBVTF UIFZ
XJMM DPNF VQ JO TPNF MBUFS FYBNQMFT JO UIF DIBQUFS CVU UIFZ
BSFOƊU FTQFDJBMMZ QFSUJOFOU UP Monad BOE XF TBX UIF HJTU PG UIFN
JO UIF QSFWJPVT DIBQUFS 4P MFUƊT UVSO PVS BUUFOUJPO CBDL UP
NPOBET TIBMM XF

 %P TZOUBY BOE NPOBET


8F JOUSPEVDFE do TZOUBY JO UIF .PEVMFT DIBQUFS 8F XFSF
VTJOH JU XJUIJO UIF DPOUFYU PG IO BT TZOUBDUJD TVHBS UIBU BMMPXFE
VT UP FBTJMZ TFRVFODF BDUJPOT CZ GFFEJOH UIF SFTVMU PG POF BDUJPO
BT UIF JOQVU WBMVF UP UIF OFYU 8IJMF do TZOUBY XPSLT XJUI
BOZ NPOBE ƈ OPU KVTU IO ƈ JU JT NPTU DPNNPOMZ TFFO XIFO
QFSGPSNJOH IO BDUJPOT 5IJT TFDUJPO JT HPJOH UP UBML BCPVU XIZ
do JT KVTU TVHBS BOE EFNPOTUSBUF XIBU UIF join PG Monad DBO EP
$)"15&3  .0/"% 

GPS VT 8F XJMM CF VTJOH UIF IO Monad UP EFNPOTUSBUF IFSF CVU


MBUFS PO XFƊMM TFF TPNF FYBNQMFT PG do TZOUBY XJUIPVU IO
5P CFHJO MFUƊT MPPL BU TPNF DPSSFTQPOEFODFT

(*>) :: Applicative f => f a -> f b -> f b

(>>) :: Monad m => m a -> m b -> m b

'PS PVS QVSQPTFT (*>) BOE (>>) BSF UIF TBNF UIJOH TFRVFOD
JOH GVODUJPOT CVU XJUI UXP EJƵFSFOU DPOTUSBJOUT 5IFZ TIPVME
JO BMM DBTFT EP UIF TBNF UIJOH

Prelude> putStrLn "Hello, " >> putStrLn "World!"


Hello,
World!
Prelude> putStrLn "Hello, " *> putStrLn "World!"
Hello,
World!

/PU PCTFSWBCMZ EJƵFSFOU (PPE FOPVHI GPS HPWFSONFOU


XPSL
8F DBO TFF XIBU do TZOUBY MPPLT MJLF BǒFS UIF DPNQJMFS
EFTVHBST JU GPS VT CZ NBOVBMMZ USBOTGPSNJOH JU PVSTFMWFT
$)"15&3  .0/"% 

import Control.Applicative ((*>))

sequencing :: IO ()
sequencing = do
putStrLn "blah"
putStrLn "another thing"

sequencing' :: IO ()
sequencing' =
putStrLn "blah" >>
putStrLn "another thing"

sequencing'' :: IO ()
sequencing'' =
putStrLn "blah" *>
putStrLn "another thing"

:PV TIPVME IBWF IBE UIF TBNF SFTVMUT GPS FBDI PG UIF BCPWF
8F DBO EP UIF TBNF XJUI UIF WBSJBCMF CJOEJOH UIBU do TZOUBY
JODMVEFT
$)"15&3  .0/"% 

binding :: IO ()
binding = do
name <- getLine
putStrLn name

binding' :: IO ()
binding' =
getLine >>= putStrLn

*OTUFBE PG OBNJOH UIF WBSJBCMF BOE QBTTJOH UIBU BT BO BS


HVNFOU UP UIF OFYU GVODUJPO XF KVTU VTF >>= XIJDI QBTTFT JU
EJSFDUMZ

8IFO GNBQ BMPOF JTOƊU FOPVHI


/PUF UIBU JG ZPV USZ UP fmap putStrLn PWFS getLine JU XPOƊU EP
BOZUIJOH 5SZ UZQJOH UIJT JOUP ZPVS 3&1-

Prelude> putStrLn <$> getLine

:PVƊWF VTFE getLine TP XIFO ZPV IJU ƉFOUFSƊ JU TIPVME BXBJU


ZPVS JOQVU 5ZQF TPNFUIJOH JO IJU ƉFOUFSƊ BHBJO BOE TFF XIBU
IBQQFOT
8IBUFWFS JOQVU ZPV HBWF JU EJEOƊU QSJOU BMUIPVHI JU TFFNT
MJLF JU TIPVME IBWF EVF UP UIF putStrLn CFJOH NBQQFE PWFS UIF
getLine 8F FWBMVBUFE UIF IO BDUJPO UIBU SFRVFTUT JOQVU CVU OPU
UIF POF UIBU QSJOUT JU 4P XIBU IBQQFOFE
$)"15&3  .0/"% 

8FMM MFUƊT TUBSU XJUI UIF UZQFT 5IF UZQF PG XIBU ZPV KVTU
USJFE UP EP JT UIJT

Prelude> :t putStrLn <$> getLine


putStrLn <$> getLine :: IO (IO ())

8FƊSF HPJOH UP CSFBL JU EPXO B MJUUMF CJU TP UIBU XFƊMM VOEFS


TUBOE XIZ UIJT EJEOƊU XPSL 'JSTU getLine QFSGPSNT IO UP HFU B
String

getLine :: IO String

"OE putStrLn UBLFT B String BSHVNFOU QFSGPSNT IO BOE SF


UVSOT OPUIJOH JOUFSFTUJOH ƈ QBSFOUT PG DIJMESFO XJUI BO BM
MPXBODF DBO TZNQBUIJ[F

putStrLn :: String -> IO ()

8IBU JT UIF UZQF PG fmap BT JU DPODFSOT putStrLn BOE getLine

-- The type we start with


<$> :: Functor f => (a -> b) -> f a -> f b

-- Our (a -> b) is putStrLn


(a -> b )
putStrLn :: String -> IO ()
$)"15&3  .0/"% 

5IBU ԑ HFUT TQFDJBMJ[FE UP UIF UZQF IO () XIJDI JT HPJOH UP


KBN BOPUIFS IO BDUJPO JOTJEF PG UIF IO UIBU getLine QFSGPSNT
1FSIBQT UIJT MPPLT GBNJMJBS GSPN PVS EFNPOTUSBUJPO PG XIBU
IBQQFOT XIFO ZPV VTF fmap UP NBQ B GVODUJPO XJUI UZQF (a ->
m b) JOTUFBE PG KVTU (a -> b) ƈ UIBU JT XIBUƊT IBQQFOJOH IFSF
4P UIJT JT XIBU JT IBQQFOJOH XJUI PVS UZQFT

f :: Functor f => f String -> f (IO ())


f x = putStrLn <$> x

g :: (String -> b) -> IO b


g x = x <$> getLine

putStrLn <$> getLine :: IO (IO ())

0LBZTP XIJDI IO JT XIJDI BOE XIZ EPFT JU BTL GPS JOQVU


CVU OPU QSJOU XIBU XF UZQFE JO

-- [1] [2] [3]


h :: IO (IO ())
h = putStrLn <$> getLine

 5IJT PVUFSNPTU IO TUSVDUVSF SFQSFTFOUT UIF FƵFDUT getLine


NVTU QFSGPSN UP HFU ZPV B String UIBU UIF VTFS UZQFE JO

 5IJT JOOFS IO TUSVDUVSF SFQSFTFOUT UIF FƵFDUT UIBU XPVME


CF QFSGPSNFE JG putStrLn XBT FWBMVBUFE
$)"15&3  .0/"% 

 5IF VOJU IFSF JT UIF VOJU UIBU putStrLn SFUVSOT

0OF PG UIF TUSFOHUIT PG )BTLFMM JT UIBU XF DBO SFGFS UP DPN


QPTF BOE NBQ PWFS FƵFDUGVM DPNQVUBUJPOT XJUIPVU QFSGPSN
JOH UIFN PS CFOEJOH PWFS CBDLXBSET UP NBLF UIBU QBUUFSO
XPSL 'PS B TJNQMFS FYBNQMF PG IPX XF DBO XBJU UP FWBMVBUF
IO BDUJPOT PS BOZ DPNQVUBUJPO JO HFOFSBM SFBMMZ
DPOTJEFS UIF
GPMMPXJOH

Prelude> let printOne = putStrLn "1"


Prelude> let printTwo = putStrLn "2"
Prelude> let twoActions = (printOne, printTwo)
Prelude> :t twoActions
twoActions :: (IO (), IO ())

8JUI UIBU UVQMF PG UXP IO BDUJPOT EFƶOFE XF DBO OPX HSBC


POF BOE FWBMVBUF JU

Prelude> fst twoActions


1
Prelude> snd twoActions
2
Prelude> fst twoActions
1

/PUF UIBU XF BSF BCMF UP FWBMVBUF IO BDUJPOT NVMUJQMF UJNFT


5IJT XJMM CF TJHOJƶDBOU MBUFS
$)"15&3  .0/"% 

#BDL UP PVS DPOVOESVN PG XIZ XF DBOƊU KVTU fmap putStrLn


PWFS getLine 1FSIBQT ZPVƊWF BMSFBEZ ƶHVSFE PVU XIBU XF OFFE
UP EP 8F OFFE UP KPJO UIPTF UXP IO MBZFST UPHFUIFS 5P HFU
XIBU XF XBOU XF OFFE UIF VOJRVF UIJOH UIBU .POBE PƵFST
join 8BUDI JU XPSL

Prelude> import Control.Monad (join)


Prelude> join $ putStrLn <$> getLine
blah
blah
Prelude> :t join $ putStrLn <$> getLine
join $ putStrLn <$> getLine :: IO ()

.0/"% *5Ɗ4 (05 8)"5 $0%&34 $3"7&


8IBU join EJE IFSF JT NFSHF UIF FƵFDUT PG getLine BOE putStrLn
JOUP B TJOHMF IO BDUJPO 5IJT NFSHFE IO BDUJPO QFSGPSNT UIF
FƵFDUT JO UIF ƌPSEFSƍ EFUFSNJOFE CZ UIF OFTUJOH PG UIF *0
BDUJPOT "T JU IBQQFOT UIF DMFBOFTU XBZ UP FYQSFTT ƌPSEFSJOHƍ
JO B MBNCEB DBMDVMVT XJUIPVU CPMUJOH PO TPNFUIJOH VOQMFBTBOU
JT UISPVHI OFTUJOH PG FYQSFTTJPOT PS MBNCEBT
5IBUƊT SJHIU 8F TUJMM IBWFOƊU MFǒ UIF MBNCEB DBMDVMVT CFIJOE
.POBEJD TFRVFODJOH BOE do TZOUBY TFFN PO UIF TVSGBDF UP
CF WFSZ GBS SFNPWFE GSPN UIBU #VU UIFZ BSFOƊU "T XF TBJE
NPOBEJD BDUJPOT BSF TUJMM QVSF BOE UIF TFRVFODJOH PQFSBUJPOT
XF VTF IFSF BSF KVTU XBZT PG OFTUJOH MBNCEBT /PX IO JT B CJU
EJƵFSFOU BT JU EPFT BMMPX GPS TJEF FƵFDUT CVU TJODF UIPTF FƵFDUT
$)"15&3  .0/"% 

BSF DPOTUSBJOFE XJUIJO UIF IO UZQF BMM UIF SFTU PG JU JT TUJMM B


QVSF MBNCEB DBMDVMVT
4PNFUJNFT JU JT WBMVBCMF UP TVTQFOE PS PUIFSXJTF OPU QFS
GPSN BO *0 BDUJPO VOUJM TPNF EFUFSNJOBUJPO JT NBEF TP UZQFT
MJLF IO (IO ()) BSFOƊU OFDFTTBSJMZ JOWBMJE CVU ZPV TIPVME CF
BXBSF PG XIBUƊT OFFEFE UP NBLF UIJT FYBNQMF XPSL
-FUƊT HFU CBDL UP EFTVHBSJOH do TZOUBY XJUI PVS OPXFOSJDIFE
VOEFSTUBOEJOH PG XIBU NPOBET EP GPS VT

bindingAndSequencing :: IO ()
bindingAndSequencing = do
putStrLn "name pls:"
name <- getLine
putStrLn ("y helo thar: " ++ name)

bindingAndSequencing' :: IO ()
bindingAndSequencing' =
putStrLn "name pls:" >>
getLine >>=
\name -> putStrLn ("y helo thar: " ++ name)

"T UIF OFTUJOH JOUFOTJƶFT ZPV DBO TFF IPX do TZOUBY DBO
NBLF UIJOHT B CJU DMFBOFS BOE FBTJFS UP SFBE
$)"15&3  .0/"% 

twoBinds :: IO ()
twoBinds = do
putStrLn "name pls:"
name <- getLine
putStrLn "age pls:"
age <- getLine
putStrLn ("y helo thar: "
++ name ++ " who is: "
++ age ++ " years old.")

twoBinds' :: IO ()
twoBinds' =
putStrLn "name pls:" >>
getLine >>=
\name ->
putStrLn "age pls:" >>
getLine >>=
\age ->
putStrLn ("y helo thar: "
++ name ++ " who is: "
++ age ++ " years old.")
$)"15&3  .0/"% 

 &YBNQMFT PG .POBE VTF


"MM SJHIU XFƊWF TFFO XIBU JT EJƵFSFOU BCPVU Monad BOE TFFO B
TNBMM EFNPOTUSBUJPO PG XIBU UIBU EPFT GPS VT 8IBU XF OFFE
OPX JT UP TFF IPX NPOBET XPSL JO DPEF XJUI MonadT PUIFS UIBO
IO

-JTU
8FƊWF CFFO TUBSUJOH PƵ PVS FYBNQMFT PG UIFTF UZQFDMBTTFT JO
VTF XJUI MJTU FYBNQMFT CFDBVTF UIFZ DBO CF RVJUF FBTZ UP TFF
BOE VOEFSTUBOE 8F XJMM LFFQ UIJT TFDUJPO CSJFG UIPVHI BT XF
IBWF NPSF FYDJUJOH UIJOHT UP TIPX ZPV

4QFDJBMJ[JOH UIF UZQFT

5IJT QSPDFTT TIPVME CF GBNJMJBS UP ZPV CZ OPX


$)"15&3  .0/"% 

(>>=) :: Monad m => m a -> (a -> m b) -> m b


(>>=) :: [ ] a -> (a -> [ ] b) -> [ ] b

-- or more syntactically common


(>>=) :: [a] -> (a -> [b]) -> [b]

-- same as pure
return :: Monad m => a -> m a
return :: a -> [ ] a
return :: a -> [a]

&YDFMMFOU *UƊT MJLF fmap FYDFQU UIF PSEFS PG BSHVNFOUT JT


ƷJQQFE BOE XF DBO OPX HFOFSBUF NPSF MJTU PS BO FNQUZ MJTU

JOTJEF PG PVS NBQQFE GVODUJPO -FUƊT UBLF JU GPS B TQJO

&YBNQMF PG UIF -JTU .POBE JO VTF

-FUƊT TUBSU XJUI B GVODUJPO BOE JEFOUJGZ IPX UIF QBSUT ƶU XJUI
PVS NPOBEJD UZQFT

twiceWhenEven :: [Integer] -> [Integer]


twiceWhenEven xs = do
x <- xs
if even x
then [x*x, x*x]
else [x*x]
$)"15&3  .0/"% 

5IF x <- xs MJOF CJOET JOEJWJEVBM WBMVFT PVU PG UIF MJTU JOQVU
MJLF B MJTU DPNQSFIFOTJPO HJWJOH VT BO Ԑ 5IF if-then-else JT
PVS a -> m b *U UBLFT UIF JOEJWJEVBM Ԑ WBMVFT UIBU IBWF CFFO
CPVOE PVU PG PVS m a BOE DBO HFOFSBUF NPSF WBMVFT UIFSFCZ
JODSFBTJOH UIF TJ[F PG UIF MJTU
5IF m a UIBU JT PVS ƶSTU JOQVU XJMM CF UIF BSHVNFOU XF QBTT
UP JU CFMPX

Prelude> twiceWhenEven [1..3]


[1,4,4,9]

/PX USZ UIJT

twiceWhenEven :: [Integer] -> [Integer]


twiceWhenEven xs = do
x <- xs
if even x
then [x*x, x*x]
else []

"OE USZ HJWJOH JU UIF TBNF JOQVU BT BCPWF GPS FBTZ DPNQBS
JTPO
 8BT UIF SFTVMU XIBU ZPV FYQFDUFE ,FFQ QMBZJOH BSPVOE
XJUI UIJT GPSNJOH IZQPUIFTFT BCPVU XIBU XJMM IBQQFO BOE
XIZ BOE UFTUJOH UIFN JO UIF 3&1- UP EFWFMPQ BO JOUVJUJPO GPS
IPX NPOBET BSF XPSLJOH PO B TJNQMF FYBNQMF 5IF FYBNQMFT
JO UIF OFYU TFDUJPOT BSF MPOHFS BOE NPSF DPNQMFY
$)"15&3  .0/"% 

.BZCF
/PX XF DPNF UP B NPSF FYDJUJOH EFNPOTUSBUJPO PG XIBU XF
DBO EP XJUI PVS OFXGPVOE QPXFS

4QFDJBMJ[JOH UIF UZQFT

*U JT UIF TFBTPO GPS FYBNJOJOH UIF UZQFT

-- m ~ Maybe

(>>=) :: Monad m => m a -> (a -> m b) -> m b


(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b

-- same as pure
return :: Monad m => a -> m a
return :: a -> Maybe a

5IFSF TIPVME IBWF CFFO OPUIJOH TVSQSJTJOH UIFSF TP MFUƊT


HFU UP UIF NFBU PG UIF NBUUFS

6TJOH UIF .BZCF .POBE

5IJT FYBNQMF MPPLT MJLF UIF POF GSPN UIF "QQMJDBUJWF DIBQUFS
CVU JUƊT EJƵFSFOU 8F FODPVSBHF ZPV UP DPNQBSF UIF UXP BM
UIPVHI XFƊWF CFFO FYQMJDJU BCPVU XIBU FYBDUMZ JT IBQQFOJOH
IFSF :PV EFWFMPQFE TPNF JOUVUJPOT BCPWF GPS do TZOUBY BOE
$)"15&3  .0/"% 

UIF MJTU NPOBE IFSF XFƊMM CF RVJUF FYQMJDJU BCPVU XIBUƊT IBQ
QFOJOH BOE CZ UIF UJNF XF HFU UP UIF Either EFNPOTUSBUJPO
CFMPX JU TIPVME CF DMFBS -FUƊT HFU TUBSUFE

data Cow = Cow {


name :: String
, age :: Int
, weight :: Int
} deriving (Eq, Show)

noEmpty :: String -> Maybe String


noEmpty "" = Nothing
noEmpty str = Just str

noNegative :: Int -> Maybe Int


noNegative n | n >= 0 = Just n
| otherwise = Nothing

-- if Cow's name is Bess, must be under 500


weightCheck :: Cow -> Maybe Cow
weightCheck c =
let w = weight c
n = name c
in if n == "Bess" && w > 499
then Nothing
else Just c
$)"15&3  .0/"% 

mkSphericalCow :: String -> Int -> Int -> Maybe Cow


mkSphericalCow name' age' weight' =
case noEmpty name' of
Nothing -> Nothing
Just nammy ->
case noNegative age' of
Nothing -> Nothing
Just agey ->
case noNegative weight' of
Nothing -> Nothing
Just weighty ->
weightCheck (Cow nammy agey weighty)

Prelude> mkSphericalCow "Bess" 5 499


Just (Cow {name = "Bess", age = 5, weight = 499})
Prelude> mkSphericalCow "Bess" 5 500
Nothing

'JSTU XFƊMM DMFBO JU VQ XJUI Monad UIFO XFƊMM TFF XIZ XF DBOƊU
EP UIJT XJUI Applicative
$)"15&3  .0/"% 

-- Do syntax isn't just for IO.

mkSphericalCow' :: String -> Int -> Int -> Maybe Cow


mkSphericalCow' name' age' weight' = do
nammy <- noEmpty name'
agey <- noNegative age'
weighty <- noNegative weight'
weightCheck (Cow nammy agey weighty)

"OE UIJT XPSLT BT FYQFDUFE

Prelude> mkSphericalCow' "Bess" 5 500


Nothing
Prelude> mkSphericalCow' "Bess" 5 499
Just (Cow {name = "Bess", age = 5, weight = 499})

$BO XF XSJUF JU XJUI (>>=) 4VSF


$)"15&3  .0/"% 

-- Stack up dem nested lambdas.

mkSphericalCow'' :: String -> Int -> Int -> Maybe Cow


mkSphericalCow'' name' age' weight' =
noEmpty name' >>=
\ nammy ->
noNegative age' >>=
\ agey ->
noNegative weight' >>=
\ weighty ->
weightCheck (Cow nammy agey weighty)

4P XIZ DBOƊU XF EP UIJT XJUI "QQMJDBUJWF #FDBVTF PVS


weightCheck GVODUJPO EFQFOET PO UIF QSJPS FYJTUFODF PG B Cow
WBMVF BOE SFUVSOT NPSF NPOBEJD TUSVDUVSF JO JUT SFUVSO UZQF
Maybe Cow
*G ZPVS do TZOUBY MPPLT MJLF UIJT

doSomething = do
a <- f
b <- g
c <- h
pure (a, b, c)

:PV DBO SFXSJUF JU VTJOH "QQMJDBUJWF 0O UIF PUIFS IBOE JG


ZPV IBWF TPNFUIJOH MJLF UIJT
$)"15&3  .0/"% 

doSomething' n = do
a <- f n
b <- g a
c <- h b
pure (a, b, c)

:PVƊSF HPJOH UP OFFE .POBE CFDBVTF g BOE h BSF QSPEVDJOH


NPOBEJD TUSVDUVSF CBTFE PO WBMVFT UIBU DBO POMZ CF PCUBJOFE
CZ EFQFOEJOH PO WBMVFT HFOFSBUFE GSPN NPOBEJD TUSVDUVSF
:PVƊMM OFFE join UP DSVODI UIF OFTUJOH PG NPOBEJD TUSVDUVSF
CBDL EPXO *G ZPV EPOƊU CFMJFWF VT USZ USBOTMBUJOH doSomething'
UP "QQMJDBUJWF TP OP SFTPSUJOH UP >>= PS join
)FSFƊT TPNF DPEF UP LJDL UIBU BSPVOE

f :: Integer -> Maybe Integer


f 0 = Nothing
f n = Just n

g :: Integer -> Maybe Integer


g i =
if even i
then Just (i + 1)
else Nothing

h :: Integer -> Maybe String


h i = Just ("10191" ++ show i)
$)"15&3  .0/"% 

doSomething' n = do
a <- f n
b <- g a
c <- h b
pure (a, b, c)

5IF MPOH BOE TIPSU PG JU

 8JUI UIF Maybe Applicative FBDI Maybe DPNQVUBUJPO GBJMT


PS TVDDFFET JOEFQFOEFOUMZ PG FBDI PUIFS :PVƊSF KVTU MJǒ
JOH GVODUJPOT UIBU BSF BMTP Just PS Nothing PWFS Maybe WBMVFT

 8JUI UIF Maybe Monad DPNQVUBUJPOT DPOUSJCVUJOH UP UIF ƶ


OBM SFTVMU DBO DIPPTF UP SFUVSO Nothing CBTFE PO ƌQSFWJPVTƍ
DPNQVUBUJPOT

&YQMPEJOH B TQIFSJDBM DPX


8F TBJE XFƊE CF RVJUF FYQMJDJU BCPVU XIBUƊT IBQQFOJOH JO UIF
BCPWF TP MFUƊT EP UIJT UIJOH -FUƊT HFU JO UIF HVUT PG UIJT DPEF
BOE IPX CJOEJOH PWFS Maybe WBMVFT XPSLT
'PS PODF UIJT FYBNQMF JOTUBODF JT XIBUƊT BDUVBMMZ JO ()$ƊT
CBTF MJCSBSZ BU UJNF PG XSJUJOH
$)"15&3  .0/"% 

instance Monad Maybe where


return x = Just x

(Just x) >>= k = k x
Nothing >>= _ = Nothing

mkSphericalCow'' :: String -> Int -> Int -> Maybe Cow


mkSphericalCow'' name' age' weight' =
noEmpty name' >>=
\ nammy ->
noNegative age' >>=
\ agey ->
noNegative weight' >>=
\ weighty ->
weightCheck (Cow nammy agey weighty)

"OE XIBU IBQQFOT JG XF QBTT JU TPNF BSHVNFOUT


$)"15&3  .0/"% 

-- Proceeding outermost to innermost.

mkSphericalCow'' "Bess" 5 499 =


noEmpty "Bess" >>=
\ nammy ->
noNegative 5 >>=
\ agey ->
noNegative 499 >>=
\ weighty ->
weightCheck (Cow nammy agey weighty)

-- "Bess" != "", so skipping this pattern


-- noEmpty "" = Nothing
noEmpty "Bess" = Just "Bess"

4P XF QSPEVDFE UIF WBMVF Just "Bess" IPXFWFS nammy XJMM


CF KVTU UIF TUSJOH BOE OPU BMTP UIF Maybe TUSVDUVSF CFDBVTF >>=
QBTTFT Ԑ UP UIF GVODUJPO JU CJOET PWFS UIF NPOBEJD WBMVF OPU
ԜԐ )FSF XFƊMM VTF UIF Maybe Monad JOTUBODF UP FYBNJOF XIZ
$)"15&3  .0/"% 

instance Monad Maybe where


return x = Just x

(Just x) >>= k = k x
Nothing >>= _ = Nothing

noEmpty "Bess" >>= \ nammy -> (rest of the computation)


-- noEmpty "Bess" evaluated to Just "Bess"
-- So the first Just case matches.

(Just "Bess") >>= \ nammy -> ...


(Just x) >>= k = k x
-- k is \ nammy et al.
-- x is "Bess" by itself.

4P nammy JT CPVOE UP ƍ#FTTƍ BOE UIF GPMMPXJOH JT UIF XIPMF Ԛ

\ "Bess" ->
noNegative 5 >>=
\ agey ->
noNegative 499 >>=
\ weighty ->
weightCheck (Cow nammy agey weighty)

5IFO IPX EPFT UIF BHF DIFDL HP


$)"15&3  .0/"% 

mkSphericalCow'' "Bess" 5 499 =


noEmpty "Bess" >>=
\ "Bess" ->
noNegative 5 >>=
\ agey ->
noNegative 499 >>=
\ weighty ->
weightCheck (Cow "Bess" agey weighty)

-- 5 >= 0 is true, so we get Just 5


noNegative 5 | 5 >= 0 = Just 5
| otherwise = Nothing

"HBJO BMUIPVHI noNegative SFUVSOT Just 5 UIF bind GVODUJPO


XJMM QBTT  PO
$)"15&3  .0/"% 

mkSphericalCow'' "Bess" 5 499 =


noEmpty "Bess" >>=
\ "Bess" ->
noNegative 5 >>=
\ 5 ->
noNegative 499 >>=
\ weighty ->
weightCheck (Cow "Bess" 5 weighty)

-- 499 >= 0 is true, so we get Just 499


noNegative 499 | 499 >= 0 = Just 499
| otherwise = Nothing

1BTTJOH  PO

mkSphericalCow'' "Bess" 5 499 =


noEmpty "Bess" >>=
\ "Bess" ->
noNegative 5 >>=
\ 5 ->
noNegative 499 >>=
\ 499 ->
weightCheck (Cow "Bess" 5 499)
$)"15&3  .0/"% 

weightCheck (Cow "Bess" 5 499) =


let 499 = weight (Cow "Bess" 5 499)
"Bess" = name (Cow "Bess" 5 499)

-- fyi, 499 > 499 is False.


in if "Bess" == "Bess" && 499 > 499
then Nothing
else Just (Cow "Bess" 5 499)

4P JO UIF FOE XF SFUVSO Just (Cow "Bess" 5 499)

'BJM GBTU MJLF BO PWFSGVOEFE TUBSUVQ


#VU XIBU JG XF IBE GBJMFE 8FƊMM EJTTFDU UIF GPMMPXJOH DPNQV
UBUJPO

Prelude> mkSphericalCow'' "" 5 499


Nothing

"OE IPX EP UIF HVUT GBMM XIFO XF FYQMPEF UIJT QPPS CPWJOF
$)"15&3  .0/"% 

mkSphericalCow'' "" 5 499 =


noEmpty "" >>=
\ nammy ->
noNegative 5 >>=
\ agey ->
noNegative 499 >>=
\ weighty ->
weightCheck (Cow nammy agey weighty)

-- "" == "", so we get the Nothing case


noEmpty "" = Nothing
-- noEmpty str = Just str

"ǒFS XFƊWF FWBMVBUFE noEmpty "" BOE HPUUFO B Nothing WBMVF


XF VTF (>>=) )PX EPFT UIBU HP
$)"15&3  .0/"% 

instance Monad Maybe where


return x = Just x

(Just x) >>= k = k x
Nothing >>= _ = Nothing

-- noEmpty "" := Nothing


Nothing >>=
\ nammy ->

-- Just case doesn't match, so skip it.


-- (Just x) >>= k = k x

-- This is what we're doing.


Nothing >>= _ = Nothing

4P JU UVSOT PVU UIBU UIF bind GVODUJPO XJMM ESPQ UIF FOUJSF
SFTU PG UIF DPNQVUBUJPO PO UIF ƷPPS UIF NPNFOU BOZ PG UIF
GVODUJPOT QBSUJDJQBUJOH JO UIF Maybe Monad BDUJPOT QSPEVDF B
Nothing WBMVF

mkSphericalCow'' "" 5 499 =


Nothing >>= -- NOPE.

*O GBDU ZPV DBO EFNPOTUSBUF UP ZPVSTFMG UIBU UIBU TUVƵ OFWFS


HFUT VTFE XJUI bottom CVU EPFT XJUI B Just WBMVF
$)"15&3  .0/"% 

Prelude> Nothing >>= undefined


Nothing
Prelude> Just 1 >>= undefined
*** Exception: Prelude.undefined

#VU XIZ EP XF VTF UIF .BZCF "QQMJDBUJWF BOE .POBE


#FDBVTF UIJT

mkSphericalCow' :: String -> Int -> Int -> Maybe Cow


mkSphericalCow' name' age' weight' = do
nammy <- noEmpty name'
agey <- noNegative age'
weighty <- noNegative weight'
weightCheck (Cow nammy agey weighty)

JT B MPU OJDFS UIBO DBTF NBUDIJOH UIF Nothing DBTF PWFS BOE
PWFS KVTU TP XF DBO TBZ Nothing -> Nothing B NJMMJPO UJNFT -JGF
JT UPP TIPSU GPS SFQFUJUJPO XIFO DPNQVUFST MPWF UBLJOH DBSF PG
SFQFUJUJPO

&JUIFS
8IFX -FUƊT BMM KVTU CF UIBOLGVM UIBU DPX XBT GVMM PG Maybe WBMVFT
BOE OPU USJQF .PWJOH BMPOH XFƊSF HPJOH UP EFNPOTUSBUF VTF
PG UIF Either Monad TUFQ CBDL B CJU BOE MFU ZPVS JOUVJUJPOT BOE
XIBU ZPV MFBSOFE BCPVU Maybe HVJEF ZPV UISPVHI
$)"15&3  .0/"% 

4QFDJBMJ[JOH UIF UZQFT

"T BMXBZT XF QSFTFOU UIF UZQFT

-- m ~ Either e
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(>>=) :: Either e a -> (a -> Either e b) -> Either e b

-- same as pure
return :: Monad m => a -> m a
return :: a -> Either e a

8IZ EP XF LFFQ EPJOH UIJT 5P SFNJOE ZPV UIBU UIF UZQFT


BMXBZT TIPX ZPV UIF XBZ PODF ZPVƊWF ƶHVSFE UIFN PVU

6TJOH UIF &JUIFS .POBE

6TF XIBU ZPV LOPX UP HP DBSFGVMMZ UISPVHI UIJT DPEF BOE


GPMMPX UIF UZQFT 'JSTU XF EFƶOF PVS EBUBUZQFT
$)"15&3  .0/"% 

module EitherMonad where

-- years ago
type Founded = Int
-- number of programmers
type Coders = Int

data SoftwareShop =
Shop {
founded :: Founded
, programmers :: Coders
} deriving (Eq, Show)

data FoundedError =
NegativeYears Founded
| TooManyYears Founded
| NegativeCoders Coders
| TooManyCoders Coders
| TooManyCodersForYears Founded Coders
deriving (Eq, Show)

-FUƊT CSJOH TPNF GVODUJPOT OPX


$)"15&3  .0/"% 

validateFounded :: Int -> Either FoundedError Founded


validateFounded n
| n < 0 = Left $ NegativeYears n
| n > 500 = Left $ TooManyYears n
| otherwise = Right n

-- Tho, many programmers *are* negative.


validateCoders :: Int -> Either FoundedError Coders
validateCoders n
| n < 0 = Left $ NegativeCoders n
| n > 5000 = Left $ TooManyCoders n
| otherwise = Right n

mkSoftware :: Int -> Int -> Either FoundedError SoftwareShop


mkSoftware years coders = do
founded <- validateFounded years
programmers <- validateCoders coders
if programmers > div founded 10
then Left $ TooManyCodersForYears founded programmers
else Right $ Shop founded programmers

/PUF UIBU Either BMXBZT TIPSUDJSDVJUT PO UIF ƶSTU UIJOH UP


IBWF GBJMFE *U NVTU CFDBVTF JO UIF Monad MBUFS WBMVFT DBO EFQFOE
PO QSFWJPVT POFT

Prelude> mkSoftware 0 0
$)"15&3  .0/"% 

Right (Shop {founded = 0, programmers = 0})

Prelude> mkSoftware (-1) 0


Left (NegativeYears (-1))

Prelude> mkSoftware (-1) (-1)


Left (NegativeYears (-1))

Prelude> mkSoftware 0 (-1)


Left (NegativeCoders (-1))

Prelude> mkSoftware 500 0


Right (Shop {founded = 500, programmers = 0})

Prelude> mkSoftware 501 0


Left (TooManyYears 501)

Prelude> mkSoftware 501 501


Left (TooManyYears 501)

Prelude> mkSoftware 100 5001


Left (TooManyCoders 5001)

Prelude> mkSoftware 0 500


Left (TooManyCodersForYears 0 500)
$)"15&3  .0/"% 

4P UIFSF JT OP Monad GPS Validation "QQMJDBUJWF BOE .POBE


JOTUBODFT NVTU IBWF UIF TBNF CFIBWJPS 5IJT JT VTVBMMZ FY
QSFTTFE JO UIF GPSN

import Control.Monad (ap)

(<*>) == ap

5IJT JT B XBZ PG TBZJOH UIF "QQMJDBUJWF BQQMZ GPS B UZQF NVTU


OPU DIBOHF CFIBWJPS JG EFSJWFE GSPN UIF .POBE JOTUBODFƊT
CJOE PQFSBUJPO

-- Keeping in mind
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
ap :: Monad m => m (a -> b) -> m a -> m b

5IFO EFSJWJOH "QQMJDBUJWF (<*>) GSPN UIF TUSPOHFS JOTUBODF

ap :: (Monad m) => m (a -> b) -> m a -> m b


ap m m' = do
x <- m
x' <- m'
return (x x')

5IF QSPCMFN JT ZPV DBOƊU NBLF B .POBE GPS 7BMJEBUJPO


UIBU BDDVNVMBUFT UIF FSSPST MJLF UIF "QQMJDBUJWF EPFT *OTUFBE
BOZ .POBE JOTUBODF GPS 7BMJEBUJPO XPVME CF JEFOUJDBM UP UIF
&JUIFSƊT NPOBE JOTUBODF
$)"15&3  .0/"% 

4IPSU &YFSDJTF &JUIFS .POBE

*NQMFNFOU UIF &JUIFS .POBE

data Sum a b =
First a
| Second b
deriving (Eq, Show)

instance Functor (Sum a) where


fmap = undefined

instance Applicative (Sum a) where


pure = undefined
(<*>) = undefined

instance Monad (Sum a) where


return = pure
(>>=) = undefined

 .POBE MBXT


5IF Monad UZQFDMBTT IBT MBXT KVTU BT UIF PUIFS UZQFDMBTTFT EP
5IFTF MBXT FYJTU BT XJUI BMM UIF PUIFS UZQFDMBTT MBXT UP FOTVSF
UIBU ZPVS DPEF EPFT OPUIJOH TVSQSJTJOH PS IBSNGVM *G UIF Monad
JOTUBODF ZPV XSJUF GPS ZPVS UZQF BCJEFT CZ UIFTF MBXT UIFO
$)"15&3  .0/"% 

ZPVS NPOBET TIPVME XPSL BT ZPV XBOU UIFN UP 5P XSJUF ZPVS
PXO JOTUBODF ZPV POMZ IBWF UP EFƶOF B >>= PQFSBUJPO CVU ZPV
XBOU ZPVS CJOEJOH UP CF BT QSFEJDUBCMF BT QPTTJCMF

*EFOUJUZ MBXT
Monad IBT UXP JEFOUJUZ MBXT

-- right identity
m >>= return = m

-- left identity
return x >>= f = f x

#BTJDBMMZ CPUI PG UIFTF MBXT BSF TBZJOH UIBU return TIPVME CF


OFVUSBM BOE OPU QFSGPSN BOZ DPNQVUBUJPO 8FƊMM MJOF UIFN VQ
XJUI UIF UZQF PG >>= UP DMBSJGZ XIBUƊT IBQQFOJOH

(>>=) :: Monad m => m a -> (a -> m b) -> m b


-- [1] [2] [3]

'JSTU SJHIU JEFOUJUZ

return :: a -> m a

m >>= return = m
-- [1] [2] [3]
$)"15&3  .0/"% 

5IF Ԝ EPFT SFQSFTFOU BO m a BOE m b SFTQFDUJWFMZ TP UIF


TUSVDUVSF JT UIFSF FWFO JG JUƊT OPU BQQBSFOU GSPN UIF XBZ UIF
MBX JT XSJUUFO
"OE MFǒ JEFOUJUZ

-- applying return to x gives us an


-- m a value to start

return x >>= f = f x
-- [1] [2] [3]

+VTU MJLF pure return TIPVMEOƊU DIBOHF BOZ PG UIF CFIBWJPS


PG UIF SFTU PG UIF GVODUJPO JU JT POMZ UIFSF UP QVU UIJOHT JOUP
TUSVDUVSF XIFO XF OFFE UP BOE UIF FYJTUFODF PG UIF TUSVDUVSF
TIPVME OPU BƵFDU UIF DPNQVUBUJPO

"TTPDJBUJWJUZ
5IF MBX PG BTTPDJBUJWJUZ JT OPU TP EJƵFSFOU GSPN PUIFS MBXT PG
BTTPDJBUJWJUZ XF IBWF TFFO *U EPFT MPPL B CJU EJƵFSFOU CFDBVTF
PG UIF OBUVSF PG >>=

(m >>= f) >>= g = m >>= (\x -> f x >>= g)

3FHSPVQJOH UIF GVODUJPOT TIPVME OPU IBWF BOZ JNQBDU PO


UIF ƶOBM SFTVMU TBNF BT UIF BTTPDJBUJWJUZ PG Monoid 5IF TZOUBY
UIFSF JO XIJDI GPS UIF SJHIU TJEF PG UIF FRVBMT TJHO XF IBE UP
$)"15&3  .0/"% 

QBTT JO BO ԧ BSHVNFOU NJHIU TFFN DPOGVTJOH BU ƶSTU 4P MFUƊT


MPPL BU JU NPSF DBSFGVMMZ
5IJT TJEF MPPLT UIF XBZ XF FYQFDU JU UP

(m >>= f) >>= g

#VU SFNFNCFS UIBU bind BMMPXT UIF SFTVMU WBMVF PG POF GVOD
UJPO UP CF QBTTFE BT JOQVU UP UIF OFYU MJLF GVODUJPO BQQMJDBUJPO
CVU XJUI PVS WBMVF BU UIF MFǒ BOE TVDDFTTJWF GVODUJPOT QSPDFFE
JOH UP UIF SJHIU 3FNFNCFS UIJT DPEF

getLine >>= putStrLn

5IF *0 GPS HFU-JOF JT FWBMVBUFE ƶSTU UIFO QVU4US-O JT QBTTFE


UIF JOQVU TUSJOH UIBU SFTVMUFE GSPN SVOOJOH HFU-JOFƊT FƵFDUT
5IJT MFǒUPSJHIU JT QBSUMZ EPXO UP UIF IJTUPSZ PG *0 JO )BTLFMM
ƈ JUƊT TP UIF ƌPSEFSƍ PG UIF DPEF SFBET UPQ UP CPUUPN 8FƊMM
FYQMBJO UIJT NPSF MBUFS JO UIF CPPL
8IFO XF SFBTTPDJBUF UIFN XF OFFE UP BQQMZ ԕ TP UIBU Ԗ IBT
BO JOQVU WBMVF PG UZQF m a UP TUBSU UIF XIPMF UIJOH PƵ 4P XF
QBTT JO UIF BSHVNFOU ԧ WJB BO BOPOZNPVT GVODUJPO

m >>= (\x -> f x >>= g)

"OE CBEB CJOH OPX OPUIJOH DBO TMPX UIJT SPMM


$)"15&3  .0/"% 

8FƊSF EPJOH UIBU UIJOH BHBJO


0VU PG NFSDZ XFƊMM CF VTJOH DIFDLFST OPU /JYPOƊT EPH
BHBJO
5IF BSHVNFOU UIF NPOBE 5FTU#BUDI XBOUT JT JEFOUJDBM UP UIF
"QQMJDBUJWF B UVQMF PG UISFF WBMVF UZQFT FNCFEEFE JO UIF
TUSVDUVSBM UZQF

Prelude> quickBatch (monad [(1, 2, 3)])

monad laws:
left identity: +++ OK, passed 500 tests.
right identity: +++ OK, passed 500 tests.
associativity: +++ OK, passed 500 tests.

(PJOH GPSXBSE XFƊMM CF VTJOH UIJT UP WBMJEBUF .POBE JO


TUBODFT -FUƊT XSJUF B CBE .POBE UP TFF XIBU JU DBO DBUDI GPS
VT

#BE .POBET BOE UIFJS EFOJ[FOT

8FƊSF HPJOH UP XSJUF BO JOWBMJE .POBE BOE 'VODUPS


 :PV
DPVME QSFUFOE JUƊT *EFOUJUZ XJUI BO JOUFHFS UISPXO JO XIJDI
HFUT JODSFNFOUFE PO FBDI GNBQ PS CJOE
$)"15&3  .0/"% 

module BadMonad where

import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes

data CountMe a =
CountMe Integer a
deriving (Eq, Show)

instance Functor CountMe where


fmap f (CountMe i a) = CountMe (i + 1) (f a)

instance Applicative CountMe where


pure = CountMe 0
CountMe n f <*> CountMe n' a = CountMe (n + n') (f a)

instance Monad CountMe where


return = pure

CountMe n a >>= f =
let CountMe _ b = f a
in CountMe (n + 1) b
$)"15&3  .0/"% 

instance Arbitrary a => Arbitrary (CountMe a) where


arbitrary = CountMe <$> arbitrary <*> arbitrary

instance Eq a => EqProp (CountMe a) where (=-=) = eq

main = do
let trigger = undefined :: CountMe (Int, String, Int)
quickBatch $ functor trigger
quickBatch $ applicative trigger
quickBatch $ monad trigger

8IFO XF SVO UIF UFTUT UIF 'VODUPS BOE .POBE XJMM GBJM UPQ
UP CPUUPN 5IF "QQMJDBUJWF UFDIOJDBMMZ POMZ GBJMFE UIF MBXT
CFDBVTF 'VODUPS EJE JO UIF "QQMJDBUJWF JOTUBODF XF XFSF VTJOH
B QSPQFS NPOPJEPGTUSVDUVSF

Prelude> main

functor:
identity: *** Failed! Falsifiable (after 1 test):
CountMe 0 0
compose: *** Failed! Falsifiable (after 1 test):
<function>
<function>
CountMe 0 0
$)"15&3  .0/"% 

applicative:
identity: +++ OK, passed 500 tests.
composition: +++ OK, passed 500 tests.
homomorphism: +++ OK, passed 500 tests.
interchange: +++ OK, passed 500 tests.
functor: *** Failed! Falsifiable (after 1 test):
<function>
CountMe 0 0

monad laws:
left identity: *** Failed! Falsifiable (after 1 test):
<function>
0
right identity: *** Failed! Falsifiable (after 1 test):
CountMe 0 0
associativity: *** Failed! Falsifiable (after 1 test):
CountMe 0 0

8F DBO BDUVBMMZ SFBQQMZ UIF XFJSE CSPLFO JODSFNFOU TF


NBOUJDT BOE HFU B CSPLFO "QQMJDBUJWF BT XFMM

instance Applicative CountMe where


pure = CountMe 0
CountMe n f <*> CountMe _ a = CountMe (n + 1) (f a)

/PX JUƊT BMM CSPLFO


$)"15&3  .0/"% 

applicative:
identity:
*** Failed! Falsifiable (after 1 test):
CountMe 0 0
composition:
*** Failed! Falsifiable (after 1 test):
CountMe 0 <function>
CountMe 0 <function>
CountMe 0 0
homomorphism:
*** Failed! Falsifiable (after 1 test):
<function>
0
interchange:
*** Failed! Falsifiable (after 3 tests):
CountMe (-1) <function>
0

6OEFSTUBOEJOH XIBU NBLFT TFOTF TUSVDUVSBMMZ GPS B 'VOD


UPS "QQMJDBUJWF BOE .POPJE DBO UFMM ZPV XIBU JT QPUFOUJBMMZ
BO JOWBMJE JOTUBODF CFGPSF ZPVƊWF XSJUUFO BOZ DPEF *ODJEFO
UBMMZ FWFO JG ZPV ƶY UIF 'VODUPS BOE "QQMJDBUJWF JOTUBODFT UIF
.POBE JOTUBODF JT OPU ZFU ƶYFE
$)"15&3  .0/"% 

instance Functor CountMe where


fmap f (CountMe i a) = CountMe i (f a)

instance Applicative CountMe where


pure = CountMe 0
CountMe n f <*> CountMe n' a =
CountMe (n + n') (f a)

instance Monad CountMe where


return = pure

CountMe _ a >>= f = f a

5IJTƊMM QBTT BT B WBMJE 'VODUPS BOE "QQMJDBUJWF CVU JUƊT OPU B


WBMJE .POBE 5IF QSPCMFN JT UIBU XIJMF pure TFUUJOH UIF JOUFHFS
WBMVF UP [FSP JT ƶOF GPS UIF QVSQPTFT PG UIF "QQMJDBUJWF CVU JU
WJPMBUFT UIF SJHIU JEFOUJUZ MBX PG .POBE

Prelude> CountMe 2 "blah" >>= return


CountMe 0 "blah"

4P PVS ƌQVSFƍ JT UPP PQJOJPOBUFE 4UJMM B WBMJE "QQMJDBUJWF


BOE 'VODUPS CVU XIBU JG pure EJEOƊU BHSFF XJUI UIF .POPJE PG
UIF TUSVDUVSF 5IF GPMMPXJOH XJMM QBTT UIF 'VODUPS MBXT CVU JU
JTOƊU B WBMJE "QQMJDBUJWF
$)"15&3  .0/"% 

instance Functor CountMe where


fmap f (CountMe i a) = CountMe i (f a)

instance Applicative CountMe where


pure = CountMe 1
CountMe n f <*> CountMe n' a =
CountMe (n + n') (f a)

"T JU IBQQFOT JG XF KVTU DIBOHF UIF .POPJEPGTUSVDUVSF UP


NBUDI UIF JEFOUJUZ TVDI UIBU XF IBWF BEEJUJPO BOE UIF OVNCFS
[FSP JUƊT B WBMJE "QQMJDBUJWF BHBJO

instance Applicative CountMe where


pure = CountMe 0
CountMe n f <*> CountMe n' a =
CountMe (n + n') (f a)

"T ZPV HBJO FYQFSJFODF XJUI UIFTF TUSVDUVSFT ZPVƊMM MFBSO


UP JEFOUJGZ XIBU NJHIU IBWF B WBMJE "QQMJDBUJWF CVU OP WBMJE
.POBE JOTUBODF #VU IPX EP XF ƶY UIF .POBE JOTUBODF #Z
ƶYJOH UIF VOEFSMZJOH .POPJE
$)"15&3  .0/"% 

instance Monad CountMe where


return = pure

CountMe n a >>= f =
let CountMe n' b = f a
in CountMe (n + n') b

0ODF PVS .POBE JOTUBODF TUBSUT TVNNJOH UIF DPVOUT MJLF


UIF "QQMJDBUJWF EJE JU XPSLT ƶOF *U DBO CF FBTZ BU UJNFT UP
BDDJEFOUBMMZ XSJUF BO JOWBMJE .POBE UIBU UZQFDIFDLT TP JUƊT JN
QPSUBOU UP VTF 2VJDL$IFDL UP WBMJEBUF ZPVS .POPJE 'VODUPS
"QQMJDBUJWF BOE .POBE JOTUBODFT

 "QQMJDBUJPO BOE DPNQPTJUJPO


8IBU XFƊWF TFFO TP GBS IBT CFFO QSJNBSJMZ BCPVU GVODUJPO
BQQMJDBUJPO 8F QSPCBCMZ XFSFOƊU UIJOLJOH UPP NVDI BCPVU UIF
SFMBUJPOTIJQ CFUXFFO GVODUJPO BQQMJDBUJPO BOE DPNQPTJUJPO
CFDBVTF XJUI Functor BOE Applicative JU IBEOƊU NBUUFSFE NVDI
#PUI DPODFSOFE GVODUJPOT UIBU MPPLFE MJLF UIF VTVBM (a -> b)
BSSBOHFNFOU TP DPNQPTJUJPO ƌKVTU XPSLFEƍ BOE UIBU UIJT XBT
USVF XBT HVBSBOUFFE CZ UIF MBXT PG UIPTF UZQFDMBTTFT
$)"15&3  .0/"% 

fmap id = id

-- guarantees

fmap f . fmap g = fmap (f . g)

8IJDI NFBOT DPNQPTJUJPO VOEFS GVODUPST KVTU XPSLT

Prelude> fmap ((+1) . (+2)) [1..5]


[4,5,6,7,8]
Prelude> fmap (+1) . fmap (+2) $ [1..5]
[4,5,6,7,8]

8JUI .POBE UIF TJUVBUJPO TFFNT MFTT OFBU BU ƶSTU -FUƊT


BUUFNQU UP EFƶOF DPNQPTJUJPO GPS NPOBEJD GVODUJPOT JO B
TJNQMF XBZ

mcomp :: Monad m =>


(b -> m c)
-> (a -> m b)
-> a -> m c
mcomp f g a = f (g a)

*G XF USZ UP MPBE UIJT XFƊMM HFU BO FSSPS MJLF UIJT

Couldn't match expected type ‘b’


with actual type ‘m b’
$)"15&3  .0/"% 

‘b’ is a rigid type variable bound


by the type signature for
mcomp :: Monad m =>
(b -> m c)
-> (a -> m b)
-> a -> m c
at kleisli.hs:21:9
Relevant bindings include
g :: a -> m b (bound at kleisli.hs:22:8)
f :: b -> m c (bound at kleisli.hs:22:6)
mcomp :: (b -> m c)
-> (a -> m b)
-> a -> m c
(bound at kleisli.hs:22:1)
In the first argument of ‘f’, namely ‘(g a)’
In the expression: f (g a)
Failed, modules loaded: none.

8FMM UIBU EJEOƊU XPSL 5IBU FSSPS NFTTBHF JT UFMMJOH VT UIBU


ԕ JT FYQFDUJOH B b GPS JUT ƶSTU BSHVNFOU CVU Ԗ JT QBTTJOH BO m b
UP ԕ 4P IPX EP XF BQQMZ B GVODUJPO JO UIF QSFTFODF PG TPNF
DPOUFYU UIBU XF XBOU UP JHOPSF 8F VTF fmap 5IBUƊT HPJOH UP
HJWF VT BO m (m c) JOTUFBE PG BO m c TP XFƊMM XBOU UP join UIPTF
UXP NPOBEJD TUSVDUVSFT
$)"15&3  .0/"% 

mcomp :: Monad m =>


(b -> m c)
-> (a -> m b)
-> a -> m c
mcomp f g a = join (f <$> (g a))

#VU VTJOH join BOE fmap UPHFUIFS NFBOT XF DBO HP BIFBE


BOE KVTU VTF (>>=)

mcomp'' :: Monad m =>


(b -> m c)
-> (a -> m b)
-> a -> m c
mcomp'' f g a = g a >>= f

:PV EPOƊU OFFE UP XSJUF BOZUIJOH TQFDJBM UP NBLF NPOBEJD


GVODUJPOT DPNQPTF BT MPOH BT UIF NPOBEJD DPOUFYUT BSF UIF
TBNF .POBE
CFDBVTF )BTLFMM IBT JU DPWFSFE XIBU ZPV XBOU
JT ,MFJTMJ DPNQPTJUJPO %POƊU TXFBU UIF TUSBOHF OBNF JUƊT OPU BT
XFJSE BT JU TPVOET "T XF TBX BCPWF XIBU XF OFFE JT GVODUJPO
DPNQPTJUJPO XSJUUFO JO UFSNT PG >>= UP BMMPX VT UP EFBM XJUI
UIF FYUSB TUSVDUVSF BOE UIBUƊT XIBU UIF ,MFJTMJ ƶTI HJWFT VT
-FUƊT SFNJOE PVSTFMWFT PG UIF UZQFT PG PSEJOBSZ GVODUJPO
DPNQPTJUJPO BOE >>=
$)"15&3  .0/"% 

(.) :: (b -> c) -> (a -> b) -> a -> c

(>>=) :: Monad m => m a -> (a -> m b) -> m b

5P HFU ,MFJTMJ DPNQPTJUJPO PƵ UIF HSPVOE XF IBWF UP ƷJQ


TPNF BSHVNFOUT BSPVOE UP NBLF UIF UZQFT XPSL

import Control.Monad

-- notice the order is flipped to match >>=

(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c

4FF BOZ TJNJMBSJUJFT UP TPNFUIJOH ZPV LOPX ZFU

(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c


flip (.) :: (a -> b) -> (b -> c) -> a -> c

*UƊT GVODUJPO DPNQPTJUJPO XJUI NPOBEJD TUSVDUVSF IBOHJOH


PƵ UIF GVODUJPOT XFƊSF DPNQPTJOH -FUƊT TFF BO FYBNQMF
$)"15&3  .0/"% 

import Control.Monad ((>=>))

sayHi :: String -> IO String


sayHi greeting = do
putStrLn greeting
getLine

readM :: Read a => String -> IO a


readM = return . read

getAge :: String -> IO Int


getAge = sayHi >=> readM

askForAge :: IO Int
askForAge = getAge "Hello! How old are you? "

8F VTFE return DPNQPTFE XJUI read UP UVSO JU JOUP TPNF


UIJOH UIBU QSPWJEFT NPOBEJD TUSVDUVSF BǒFS CFJOH CPVOE PWFS
UIF PVUQVU PG sayHi 8F OFFEFE UIF LMFJTMJ DPNQPTJUJPO PQFSB
UPS UP TUJUDI sayHi BOE readM UPHFUIFS
$)"15&3  .0/"% 

sayHi :: String -> IO String


readM :: Read a => String -> IO a

-- [1] [2] [3] [4] [5] [6] [7] [8] [9]


(a -> m b) -> (b -> m c) -> a -> m c
String -> IO String String -> IO a String IO a

 5IF ƶSTU UZQF JT UIF UZQF PG UIF JOQVU UP sayHi 4USJOH

 5IF IO UIBU sayHi QFSGPSNT JO PSEFS UP QSFTFOU B HSFFUJOH


BOE SFDFJWF JOQVU

 5IF String JOQVU GSPN UIF VTFS UIBU sayHi SFUVSOT

 5IF String UIBU readM FYQFDUT BT BO BSHVNFOU BOE XIJDI


sayHi XJMM QSPEVDF

 5IF IO readM SFUVSOT JOUP /PUF UIBU return/pure QSPEVDF


IO WBMVFT XIJDI QFSGPSN OP FƵFDUT

 5IF Int UIBU readM SFUVSOT

 5IF PSJHJOBM JOJUJBM String JOQVU sayHi FYQFDUT TP JU LOPXT


IPX UP HSFFU UIF VTFS BOE BTL GPS UIFJS BHF

 5IF ƶOBM DPNCJOFE IO BDUJPO XIJDI QFSGPSNT BMM FƵFDUT


OFDFTTBSZ UP QSPEVDF UIF ƶOBM SFTVMU

 5IF WBMVF JOTJEF PG UIF ƶOBM IO BDUJPO JO UIJT DBTF UIJT JT


UIF Int WBMVF UIBU readM SFUVSOFE
$)"15&3  .0/"% 

 $IBQUFS &YFSDJTFT


8SJUF Monad JOTUBODFT GPS UIF GPMMPXJOH UZQFT 6TF UIF 2VJDL$IFDL
QSPQFSUJFT XF TIPXFE ZPV UP WBMJEBUF ZPVS JOTUBODFT

 8FMDPNF UP UIF /PQF .POBE XIFSF OPUIJOH IBQQFOT


BOE OPCPEZ DBSFT

data Nope a =
NopeDotJpg

-- We're serious. Write it anyway.

 data PhhhbbtttEither b a =
Left a
| Right b

 8SJUF B .POBE JOTUBODF GPS *EFOUJUZ


$)"15&3  .0/"% 

newtype Identity a = Identity a


deriving (Eq, Ord, Show)

instance Functor Identity where


fmap = undefined

instance Applicative Identity where


pure = undefined
(<*>) = undefined

instance Monad Identity where


return = pure
(>>=) = undefined

 5IJT POF TIPVME CF FBTJFS UIBO UIF "QQMJDBUJWF JOTUBODF


XBT 3FNFNCFS UP VTF UIF 'VODUPS UIBU .POBE SFRVJSFT
UIFO TFF XIFSF UIF DIJQT GBMM

data List a =
Nil
| Cons a (List a)

8SJUF UIF GPMMPXJOH GVODUJPOT VTJOH UIF NFUIPET QSPWJEFE


CZ .POBE BOE 'VODUPS 6TJOH TUVƵ MJLF JEFOUJUZ BOE DPNQPTJ
UJPO JT ƶOF CVU JU IBT UP UZQFDIFDL XJUI UZQFT QSPWJEFE

 j :: Monad m => m (m a) -> m a


$)"15&3  .0/"% 

&YQFDUJOH UIF GPMMPXJOH CFIBWJPS

Prelude> j [[1, 2], [], [3]]


[1,2,3]
Prelude> j (Just (Just 1))
Just 1
Prelude> j (Just Nothing)
Nothing
Prelude> j Nothing
Nothing

 l1 :: Monad m => (a -> b) -> m a -> m b

 l2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c

 a :: Monad m => m a -> m (a -> b) -> m b

 :PVƊMM OFFE SFDVSTJPO GPS UIJT POF

meh :: Monad m => [a] -> (a -> m b) -> m [b]

 )JOU SFVTF ƌNFIƍ

flipType :: (Monad m) => [m a] -> m [a]


$)"15&3  .0/"% 

 %FƶOJUJPO
 " NPOBE JT B UZQFDMBTT SFJGZJOH BO BCTUSBDUJPO UIBU JT DPN
NPOMZ VTFE JO )BTLFMM *OTUFBE PG BO PSEJOBSZ GVODUJPO PG
UZQF Ԑ UP ԑ ZPVƊSF GVODUPSJBMMZ BQQMZJOH B GVODUJPO XIJDI
QSPEVDFT NPSF TUSVDUVSF JUTFMG BOE VTJOH join UP SFEVDF
UIF OFTUFE TUSVDUVSF UIBU SFTVMUT

fmap :: (a -> b) -> f a -> f b

(<*>) :: f (a -> b) -> f a -> f b

(=<<) :: (a -> f b) -> f a -> f b

 " NPOBEJD GVODUJPO JT POF XIJDI HFOFSBUFT NPSF TUSVDUVSF


BǒFS IBWJOH CFFO MJǒFE PWFS NPOBEJD TUSVDUVSF $POUSBTU
UIF GVODUJPO BSHVNFOUT UP fmap BOE (>>=) JO

fmap :: (a -> b) -> f a -> f b

(>>=) :: m a -> (a -> m b) -> m b

5IF TJHOJƶDBOU EJƵFSFODF JT UIBU UIF SFTVMU JT m b BOE SF


RVJSFT joinJOH UIF SFTVMU BǒFS MJǒJOH UIF GVODUJPO PWFS
Ԝ 8IBU EPFT UIJT NFBO 5IBU EFQFOET PO UIF .POBE
JOTUBODF
$)"15&3  .0/"% 

5IF EJTUJODUJPO DBO CF TFFO XJUI PSEJOBSZ GVODUJPO DPN


QPTJUJPO BOE LMFJTMJ DPNQPTJUJPO BT XFMM

(.) :: (b -> c) -> (a -> b) -> a -> c

(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c

 CJOE JT VOGPSUVOBUFMZ B TPNFXIBU PWFSMPBEFE UFSN :PV


ƶSTU TBX JU VTFE FBSMZ JO UIF CPPL XJUI SFTQFDU UP CJOEJOH
WBSJBCMFT UP WBMVFT TVDI BT XJUI UIF GPMMPXJOH

let x = 2 in x + 2

8IFSF ԧ JT B WBSJBCMF CPVOE UP  )PXFWFS XIFO XFƊSF


UBMLJOH BCPVU B .POBE JOTUBODF UZQJDBMMZ CJOE XJMM SFGFS
UP IBWJOH VTFE >>= UP MJǒ B NPOBEJD GVODUJPO PWFS UIF
TUSVDUVSF 5IF EJTUJODUJPO CFJOH

-- lifting (a -> b) over f in f a


fmap :: (a -> b) -> f a -> f b

-- binding (a -> m b) over m in m a


(>>=) :: m a -> (a -> m b) -> m b

:PVƊMM TPNFUJNFT TFF VT UBML BCPVU UIF VTF PG UIF CJOE


doOPUBUJPO <- PS (>>=) BT ƌCJOEJOH PWFSƍ 8IFO XF EP
XF KVTU NFBO UIBU XF MJǒFE B NPOBEJD GVODUJPO BOE XFƊMM
$)"15&3  .0/"% 

FWFOUVBMMZ join PS TNVTI UIF TUSVDUVSF CBDL EPXO XIFO


XFƊSF EPOF NPOLFZJOH BSPVOE JO UIF .POBE %POƊU QBOJD
JG XFƊSF B MJUUMF DBTVBM BCPVU EFTDSJCJOH UIF VTF PG <- BT
IBWJOH CPVOE PWFSPVU TPNF Ԑ PVU PG m a

 'PMMPXVQ SFTPVSDFT


 8IBU B .POBE JT OPU
https://wiki.haskell.org/What_a_Monad_is_not

 (BCSJFM (PO[BMF[ )PX UP EFTVHBS )BTLFMM DPEF

 4UFQIFO %JFIM 8IBU * XJTI * LOFX XIFO -FBSOJOH )BTLFMM


http://dev.stephendiehl.com/hask/#monads

 4UFQIFO %JFIM .POBET .BEF %JƸDVMU


http://www.stephendiehl.com/posts/monads.html

 #SFOU :PSHFZ 5ZQFDMBTTPQFEJB


https://wiki.haskell.org/Typeclassopedia
$IBQUFS 

"QQMZJOH TUSVDUVSF

* PǒFO SFQFBU SFQFBU


NZTFMG * PǒFO SFQFBU
SFQFBU * EPOƊU EPOƊU LOPX
XIZ LOPX XIZ * TJNQMZ
LOPX UIBU * * * BN BN
JODMJOFE UP TBZ UP TBZ B MPU
B MPU UIJT XBZ UIJT XBZ *
PǒFO SFQFBU SFQFBU
NZTFMG * PǒFO SFQFBU
SFQFBU

+BDL 1SFMVUTLZ


$)"15&3  .0/"%4 (0/& 8*-% 

 "QQMJFE TUSVDUVSF


8F UIPVHIU ZPVƊE MJLF UP TFF Monoid Functor Applicative BOE
Monad JO UIF XJME BT JU XFSF 4JODF XFƊE MJLF UP ƶOJTI UIJT CPPL
CFGPSF XF IBWF HSBOEDIJMESFO UIJT XJMM OPU CF BDDPNQBOJFE
CZ UIF QBJOTUBLJOH FYQMBOBUJPOT BOE FYFSDJTF SFHJNF ZPVƊWF
FYQFSJFODFE VQ UP UIJT QPJOU %POƊU VOEFSTUBOE TPNFUIJOH
'JHVSF JU PVU 8FƊMM EP PVS CFTU UP MFBWF B USBJM PG CSFBEDSVNCT
GPS ZPV UP GPMMPX VQ PO UIF DPEF XF TIPX ZPV $POTJEFS UIJT B
CSFF[Z TVSWFZ PG ƌ)PX )BTLFMMFST XSJUF DPEF XIFO UIFZ UIJOL
OPPOF JT MPPLJOHƍ BOE B QMFBTBOU CSFBL GSPN ZPVS SFHVMBSMZ
TDIFEVMFE FYFSDJTFT 5IF DPEF EFNPOTUSBUFE XJMM OPU BMXBZT
JODMVEF BMM OFDFTTBSZ DPOUFYU UP NBLF JU SVO TP EPOƊU FYQFDU
UP CF BCMF UP MPBE UIF TOJQQFUT JO ()$J BOE IBWF UIFN XPSL
*G ZPV EPOƊU IBWF B MPU PG QSFWJPVT QSPHSBNNJOH FYQFSJFODF
BOE TPNF PG UIF BQQMJDBUJPOT BSF EJƸDVMU GPS ZPV UP GPMMPX
ZPV NJHIU QSFGFS UP SFUVSO UP UIJT DIBQUFS BU B MBUFS UJNF PODF
ZPV TUBSU USZJOH UP SFBE BOE VTF )BTLFMM MJCSBSJFT GPS QSBDUJDBM
QSPKFDUT

 .POPJE
.POPJET BSF FWFSZXIFSF PODF ZPV SFDPHOJ[F UIF QBUUFSO BOE
TUBSU MPPLJOH GPS UIFN CVU XFƊWF USJFE UP DIPPTF B GFX HPPE
FYBNQMFT UP JMMVTUSBUF UZQJDBM VTFDBTFT
$)"15&3  .0/"%4 (0/& 8*-% 

5FNQMBUJOH DPOUFOU JO 4DPUUZ


)FSF UIF 4DPUUZ XFC GSBNFXPSLƊT )FMMP 8PSME FYBNQMF VTFT
mconcat UP JOKFDU UIF QBSBNFUFS ƌXPSEƍ JOUP UIF )5.- QBHF
SFUVSOFE

{-# LANGUAGE OverloadedStrings #-}


import Web.Scotty

import Data.Monoid (mconcat)

main = scotty 3000 $ do


get "/:word" $ do
beam <- param "word"
html
(mconcat
[ "<h1>Scotty, "
, beam
, " me up!</h1>"])

*G ZPVƊSF JOUFSFTUFE JO GPMMPXJOH VQ PO UIJT FYBNQMF ZPV


DBO ƶOE UIJT FYBNQMF BOE B UVUPSJBM PO UIF 4DPUUZ (JUIVC
SFQPTJUPSZ
$)"15&3  .0/"%4 (0/& 8*-% 

$PODBUFOBUJOH DPOOFDUJPO QBSBNFUFST


5IF OFYU FYBNQMF JT GSPN "EJUZB #IBSHBWBƊT ƌ.BLJOH " 8FC
TJUF 8JUI )BTLFMM ƍ B CMPH QPTU UIBU XBMLT ZPV UISPVHI TFWFSBM
TUFQT GPS XFMM NBLJOH B TJNQMF XFCTJUF JO )BTLFMM *U BMTP VTFT
UIF 4DPUUZ XFC GSBNFXPSL
)FSF XFƊSF VTJOH foldr BOE Monoid UP DPODBUFOBUF DPOOFDUJPO
QBSBNFUFST GPS DPOOFDUJOH UP UIF EBUBCBTF

runDb :: SqlPersist (ResourceT IO) a -> IO a


runDb query = do
let connStr =
foldr (\(k,v) t ->
t <> (encodeUtf8 $
k <> "=" <> v <> " "))
"" params
runResourceT . withPostgresqlConn connStr
$ runSqlConn query

*G ZPVƊSF JOUFSFTUFE JO GPMMPXJOH VQ PO UIJT UIJT CMPH QPTU


JT POF PG NBOZ UIBU TIPXT ZPV TUFQ CZ TUFQ IPX UP VTF 4DPUUZ
BMUIPVHI NBOZ PG UIFN CSFF[F UISPVHI FBDI TUFQ XJUIPVU B
HSFBU EFBM PG FYQMBOBUJPO *U XJMM CF FBTJFS UP VOEFSTUBOE 4DPUUZ
JO EFUBJM PODF ZPVƊWF XPSLFE UISPVHI NPOBE USBOTGPSNFST CVU
JG ZPVƊE MJLF UP TUBSU QMBZJOH BSPVOE XJUI TPNF CBTJD QSPKFDUT
ZPV NBZ XBOU UP USZ UIFN PVU
$)"15&3  .0/"%4 (0/& 8*-% 

$PODBUFOBUJOH LFZ DPOƶHVSBUJPOT


5IF OFYU FYBNQMF JT HPJOH UP CF B CJU NFBUJFS UIBO UIF UXP
QSFWJPVT POFT
9.POBE JT B XJOEPXJOH TZTUFN GPS 9 XSJUUFO JO )BTLFMM
5IF DPOƶHVSBUJPO MBOHVBHF JT )BTLFMM ƈ UIF CJOBSZ UIBU SVOT
ZPVS 8. JT DPNQJMFE GSPN ZPVS QFSTPOBM DPOƶHVSBUJPO 5IF
GPMMPXJOH JT BO FYBNQMF PG VTJOH mappend UP DPNCJOF UIF EFGBVMU
DPOƶHVSBUJPOƊT LFZ NBQQJOHT BOE B NPEJƶDBUJPO PG UIPTF LFZT

import XMonad
import XMonad.Actions.Volume
import Data.Map.Lazy (fromList)
import Data.Monoid (mappend)

main = do
xmonad def { keys =
\c -> fromList [
((0, xK_F7),
lowerVolume 4 >> return ()),
((0, xK_F8),
raiseVolume 4 >> return ())
] `mappend` keys defaultConfig c
}

5IF UZQF PG keys JT B GVODUJPO


$)"15&3  .0/"%4 (0/& 8*-% 

keys :: !(XConfig Layout -> Map (ButtonMask, KeySym) (X ()))

:PV EPOƊU OFFE UP HFU UPP FYDJUFE BCPVU UIF FYDMBNBUJPO


QPJOU SJHIU OPX JUƊT UIF TZOUBY GPS B OJǒZ UIJOH DBMMFE B TUSJDUOFTT
BOOPUBUJPO XIJDI NBLFT B ƶFME JO B QSPEVDU TUSJDU 5IBU JT ZPV
XPOƊU CF BCMF UP DPOTUSVDU UIF SFDPSE PS QSPEVDU UIBU DPOUBJOT
UIF WBMVF XJUIPVU BMTP GPSDJOH UIBU ƶFME UP XFBLIFBE OPSNBM
GPSN 8FƊMM FYQMBJO UIJT JO NPSF EFUBJM MBUFS JO UIF CPPL
0, TP UIF HJTU PG UIF main GVODUJPO BCPWF JT UIBU JU BMMPXT
ZPVS LFZNBQQJOH UP CF CBTFE PO UIF DVSSFOU DPOƶHVSBUJPO
PG ZPVS FOWJSPONFOU 8IFOFWFS ZPV UZQF B LFZ 9.POBE
XJMM QBTT UIF DVSSFOU DPOƶH UP ZPVS keys GVODUJPO JO PSEFS UP
EFUFSNJOF XIBU JG BOZ
BDUJPO JU TIPVME UBLF CBTFE PO UIBU
8FƊSF VTJOH UIF Monoid IFSF UP BEE OFX LFZCPBSE TIPSUDVUT GPS
MPXFSJOH BOE SBJTJOH UIF WPMVNF XJUI ' BOE ' 5IF .POPJE
PG UIF keys GVODUJPOT JT DPNCJOJOH BMM PG UIF LFZ NBQT FBDI
GVODUJPO QSPEVDFT XIFO BQQMJFE UP UIF 9$POƶH UP QSPEVDF B
ƶOBM DBOPOJDBM LFZ NBQ
4BZ XIBU
5IJT JT B Monoid JOTUBODF XF IBEOƊU DPWFSFE JO UIF Monoid
DIBQUFS TP MFUƊT UBLF B MPPL BU JU OPX

instance Monoid b => Monoid (a -> b) -- Defined in ‘GHC.Base’

5IJT GSJFOET JT UIF .POPJE PG GVODUJPOT


#VU IPX EPFT JU XPSL 'JSTU MFUƊT TFU VQ TPNF WFSZ USJWJBM
GVODUJPOT GPS EFNPOTUSBUJPO
$)"15&3  .0/"%4 (0/& 8*-% 

Prelude> import Data.Monoid


Prelude> let f = const (Sum 1)
Prelude> let g = const (Sum 2)
Prelude> f 9001
Sum {getSum = 1}
Prelude> g 9001
Sum {getSum = 2}

2VFSZ UIF UZQFT PG UIPTF GVODUJPOT BOE TFF IPX ZPV UIJOL
UIFZ XJMM NBUDI VQ UP UIF .POPJE JOTUBODF BCPWF
8F LOPX UIBU XIBUFWFS BSHVNFOUT XF HJWF UP ԕ BOE Ԗ UIFZ
XJMM BMXBZT SFUVSO UIFJS ƶSTU BSHVNFOUT XIJDI BSF 4VN NPOPJET
4P JG XF mappend ԕ BOE Ԗ UIFZƊSF HPJOH UP JHOPSF XIBUFWFS BS
HVNFOU XF USJFE UP BQQMZ UIFN UP BOE VTF UIF .POPJE UP
DPNCJOF UIF SFTVMUT

Prelude> (f <> g) 9001


Sum {getSum = 3}

4P UIJT NPOPJE JOTUBODF BMMPXT UP NBQQFOE UIF SFTVMUT PG


UXP GVODUJPO BQQMJDBUJPOT

(a -> b) <> (a -> b)

+VTU BT MPOH BT UIF ԑ IBT B Monoid JOTUBODF


8FƊSF HPJOH UP PƵFS B GFX NPSF FYBNQMFT UIBU XJMM HFU ZPV
DMPTFS UP XIBU UIF QBSUJDVMBS VTF PG mappend JO UIF 9NPOBE
$)"15&3  .0/"%4 (0/& 8*-% 

FYBNQMF JT EPJOH 8F NFOUJPOFE Data.Map CBDL JO UIF 5FTUJOH


DIBQUFS *U HJWFT VT PSEFSFE QBJST PG LFZT BOE WBMVFT

Prelude> import qualified Data.Map as M


Prelude M> :t M.fromList
M.fromList :: Ord k => [(k, a)] -> Map k a

Prelude M> let f = M.fromList [('a', 1)]


Prelude M> let g = M.fromList [('b', 2)]
Prelude M> :t f
f :: Num a => Map Char a
Prelude M> import Data.Monoid
Prelude M Data.Monoid> f <> g
fromList [('a',1),('b',2)]
Prelude M Data.Monoid> :t (f <> g)
(f <> g) :: Num a => Map Char a

Prelude M Data.Monoid> mappend f g


fromList [('a',1),('b',2)]
Prelude M Data.Monoid> f `mappend` g
fromList [('a',1),('b',2)]

-- but note what happens here:


Prelude> M.fromList [('a', 1)] <> M.fromList [('a', 2)]
fromList [('a',1)]
$)"15&3  .0/"%4 (0/& 8*-% 

4P SFUVSOJOH UP UIF 9NPOBE DPOƶHVSBUJPO XF TUBSUFE XJUI


5IF keys ƶFME JT B GVODUJPO XIJDI HJWFO BO 9$POƶH QSPEVDFT
B LFZNBQQJOH *U VTFT UIF NPOPJE PG GVODUJPOT UP DPNCJOF UIF
QSFFYJTUJOH GVODUJPO UIBU HFOFSBUFT UIF LFZNBQ UP QSPEVDF BT
NBOZ NBQT BT ZPV IBWF NBQQFOEFE GVODUJPOT UIFO DPNCJOF
BMM UIF LFZ NBQT JOUP POF
5IJT QBSU

>> return ())

TBZT UIBU UIF LFZ BTTJHONFOU JT QFSGPSNJOH TPNF FƵFDUT BOE


POMZ QFSGPSNJOH TPNF FƵFDUT 'VODUJPOT IBWF UP SFEVDF UP
TPNF SFTVMU CVU TPNFUJNFT UIFJS POMZ QVSQPTF JT UP QFSGPSN
TPNF FƵFDUT BOE ZPV EPOƊU XBOU UP EP BOZUIJOH XJUI UIF ƌSFTVMUƍ
PG FWBMVBUJOH UIF UFSNT
"T XFƊWF TBJE BOE PUIFS QFPQMF IBWF OPUFE BT XFMM NPOPJET
BSF FWFSZXIFSF OPU KVTU JO )BTLFMM CVU JO BMM PG QSPHSBNNJOH

 'VODUPS
5IFSFƊT B SFBTPO XF DIPTF UIBU .JDIBFM /FBMF RVPUBUJPO GPS
UIF Functor DIBQUFS FQJHSBQI MJǒJOH SFBMMZ JT UIF DIFBU NPEF
fmap JT VCJRVJUPVT JO )BTLFMM GPS BMM TPSUT PG BQQMJDBUJPOT CVU
XFƊWF QJDLFE B DPVQMF UIBU XF GPVOE FTQFDJBMMZ EFNPOTUSBUJWF
PG XIZ JUƊT TP IBOEZ
$)"15&3  .0/"%4 (0/& 8*-% 

-JǒJOH PWFS *0
)FSF XFƊSF UBLJOH B GVODUJPO UIBU EPFTOƊU QFSGPSN IO addUTCTime
QBSUJBMMZ BQQMZJOH JU UP UIF PƵTFU XFƊSF HPJOH UP BEE UP UIF TFD
POE BSHVNFOU UIFO NBQQJOH JU PWFS UIF IO BDUJPO UIBU HFUT VT
UIF DVSSFOU UJNF

import Data.Time.Clock

offsetCurrentTime :: NominalDiffTime -> IO UTCTime


offsetCurrentTime offset =
fmap (addUTCTime (offset * 24 * 3600)) $
getCurrentTime

$POUFYU GPS UIF BCPWF

 NominalDiffTime JT B OFXUZQF PG Pico BOE IBT B Num JOTUBODF


UIBUƊT XIZ UIF BSJUINFUJD XPSLT

addUTCTime :: NominalDiffTime -> UTCTime -> UTCTime

 getCurrentTime :: IO UTCTime

 fmapƊT UZQF HPU TQFDJBMJ[FE

fmap :: (UTCTime -> UTCTime) -> IO UTCTime -> IO UTCTime


$)"15&3  .0/"%4 (0/& 8*-% 

)FSF XFƊSF MJǒJOH TPNF EBUB DPOWFSTJPO TUVƵ PWFS UIF GBDU
UIBU UIF 66*% MJCSBSZ IBT UP UPVDI BO PVUTJEF SFTPVSDF SBO
EPN OVNCFS HFOFSBUJPO
UP HJWF VT B SBOEPN JEFOUJƶFS 5IF
66*% MJCSBSZ VTFE JT OBNFE VVJE PO )BDLBHF 5IF Text QBDL
BHF VTFE JT OBNFEƒtext

import Data.Text (Text)


import qualified Data.Text as T
import qualified Data.UUID as UUID
import qualified Data.UUID.V4 as UUIDv4

textUuid :: IO Text
textUuid =
fmap (T.pack . UUID.toString) UUIDv4.nextRandom

 nextRandom :: IO UUID

 toString :: UUID -> String

 pack :: String -> Text

 fmap :: (UUID -> Text) -> IO UUID -> IO Text

-JǒJOH PWFS XFC BQQ NPOBET


'SFRVFOUMZ XIFO ZPV XSJUF XFC BQQMJDBUJPOT ZPVƊMM IBWF B
DVTUPN EBUBUZQF UP EFTDSJCF UIF XFC BQQMJDBUJPO XIJDI JT BMTP
$)"15&3  .0/"%4 (0/& 8*-% 

B Monad *UƊT B Monad CFDBVTF ZPVS ƌBQQ DPOUFYUƍ XJMM IBWF B


UZQF QBSBNFUFS UP EFTDSJCF XIBU SFTVMU XBT QSPEVDFE JO UIF
DPVSTF PG B SVOOJOH XFC BQQMJDBUJPO 0ǒFO UIFTF UZQFT XJMM
BCTUSBDU PVU UIF BWBJMBCJMJUZ PG B SFRVFTU PS PUIFS DPOƶHVSBUJPO
EBUB XJUI B 3FBEFS FYQMBJOFE JO B MBUFS DIBQUFS
BT XFMM BT UIF
QFSGPSNBODF PG FƵFDUT WJB IO *O UIF GPMMPXJOH FYBNQMF XFƊSF
MJǒJOH PWFS AppHandler BOE Maybe

userAgent :: AppHandler (Maybe UserAgent)


userAgent = (fmap . fmap) userAgent' getRequest

userAgent' :: Request -> Maybe UserAgent


userAgent' req =
getHeader "User-Agent" req

8F OFFE UIF Functor IFSF CFDBVTF XIJMF XF DBO KVTU QBUUFSO


NBUDI PO UIF Maybe WBMVF BO AppHandler JTOƊU TPNFUIJOH XF DBO
QBUUFSO NBUDI PO *UƊT B 4OBQ DPOWFOUJPO UP NBLF B UZQF BMJBT
GPS ZPVS XFC BQQMJDBUJPO UZQF *U VTVBMMZ MPPLT MJLF UIJT

type AppHandler = Handler App App

5IF VOEFSMZJOH JOGSBTUSVDUVSF GPS 4OBQ JT NPSF DPNQMJ


DBUFE UIBO XF DBO DPWFS UP BOZ EFQUI IFSF CVU TVƸDF UP TBZ
UIFSF BSF B GFX UIJOHT ƷPBUJOH BSPVOE

 )551 SFRVFTU XIJDI USJHHFSFE UIF QSPDFTTJOH DVSSFOUMZ


PDDVSSJOH
$)"15&3  .0/"%4 (0/& 8*-% 

 5IF DVSSFOU QPTTJCMZ FNQUZ PS EFGBVMU


SFTQPOTF UIBU XJMM
CF SFUVSOFE UP UIF DMJFOU XIFO UIF IBOEMFST BOE NJEEMF
XBSF BSF EPOF

 " GVODUJPO GPS VQEBUJOH UIF SFRVFTU UJNFPVU

 " IFMQFS GVODUJPO GPS MPHHJOH

 "OE B GBJS CJU NPSF UIBO UIJT

5IF JTTVF IFSF JT UIBU ZPVS "QQ)BOEMFS JT NFBOU UP CF TMPU


UFE JOUP B XFC BQQMJDBUJPO XIJDI SFRVJSFT UIF SFBEJOH JO PG
DPOƶHVSBUJPO JOJUJBMJ[BUJPO PG B XFC TFSWFS BOE UIF TFOEJOH
PG B SFRVFTU UP HFU FWFSZUIJOH JO NPUJPO 5IJT JT FTTFOUJBMMZ
B CVODI PG GVODUJPOT XBJUJOH GPS BSHVNFOUT ƈ XBJUJOH GPS
TPNFUIJOH UP EP *U EPFTOƊU NBLF TFOTF UP EP BMM UIBU ZPVSTFMG
FWFSZ UJNF ZPV XBOU B WBMVF UIBU DBO POMZ CF PCUBJOFE JO UIF
DPVSTF PG UIF XFC BQQMJDBUJPO EPJOH JUT UIJOH "DDPSEJOHMZ
PVS 'VODUPS JT MFUUJOH VT XSJUF GVODUJPOT PWFS TUSVDUVSF XIJDI
IBOEMFT BMM UIJT XPSL *UƊT MJLF XFƊSF TBZJOH ƌIFSFƊT B GVODUJPO
BQQMZ JU UP B UIJOH UIBU SFTVMUFE GSPN BO )551 SFRVFTU DPNJOH
EPXO UIF QJQF JG POF DPNFT BMPOHƍ

 "QQMJDBUJWF
"QQMJDBUJWF JT TPNFXIBU OFX UP )BTLFMM CVU JUƊT VTFGVM FOPVHI
QBSUJDVMBSMZ XJUI QBSTFST UIBU JUƊT FBTZ UP ƶOE FYBNQMFT 5IFSFƊT
$)"15&3  .0/"%4 (0/& 8*-% 

B XIPMF DIBQUFS PO QBSTFST DPNJOH VQ MBUFS CVU XF UIPVHIU


UIFTF FYBNQMFT XFSF NPTUMZ DPNQSFIFOTJCMF FWFO XJUIPVU
UIBU DPOUFYU

IHSFW
5IJT JT BO FYBNQMF GSPN -VLF )PFSTUFOƊT IHSFW QSPKFDU 5IF
FYBNQMF JO UIF 3&"%.& JT B CJU EFOTF CVU VTFT .POPJE BOE
"QQMJDBUJWF UP DPNCJOF QBSTFST PG DPNNBOE MJOF BSHVNFOUT

jsonSwitch :: Parser (a -> a)


jsonSwitch =
infoOption $(hgRevStateTH jsonFormat)
$ long "json"
<> short 'J'
<> help "Display JSON version information"

parserInfo :: ParserInfo (a -> a)


parserInfo = info (helper <*> verSwitch <* jsonSwitch) fullDesc

:PV NJHIU CF XPOEFSJOH XIBU UIF <* PQFSBUPS JT *UƊT BO
PUIFS PQFSBUPS GSPN UIF "QQMJDBUJWF UZQFDMBTT *U BMMPXT ZPV UP
TFRVFODF BDUJPOT EJTDBSEJOH UIF SFTVMU PG UIF TFDPOE BSHVNFOU
%PFT UIJT MPPL GBNJMJBS

Prelude> :t (<*)
(<*) :: Applicative f => f a -> f b -> f a
$)"15&3  .0/"%4 (0/& 8*-% 

Prelude> :t const
const :: a -> b -> a

#BTJDBMMZ UIF (<*) PQFSBUPS MJLF JUT TJCMJOH (*>) BOE UIF
NPOBEJD PQFSBUPS >>
JT VTFGVM XIFO ZPVƊSF FNJUUJOH FƵFDUT
*O UIJT DBTF ZPVƊWF EPOF TPNFUIJOH XJUI FƵFDUT BOE XBOU UP
EJTDBSE BOZ WBMVF UIBU SFTVMUFE

.PSF QBSTJOH
)FSF XFƊSF VTJOH Applicative UP MJǒ UIF EBUB DPOTUSVDUPS GPS UIF
Payload UZQF PWFS UIF Parser SFUVSOFE CZ SFRVFTUJOH B WBMVF CZ
LFZ PVU PG B +40/ PCKFDU XIJDI JT CBTJDBMMZ BO BTTPDJBUJPO PG
UFYU LFZT UP GVSUIFS NPSF +40/ WBMVFT XIJDI NBZ CF TUSJOHT
OVNCFST BSSBZT PS NPSF +40/ PCKFDUT

parseJSON :: Value -> Parser a


(.:) :: FromJSON a => Object -> Text -> Parser a

instance FromJSON Payload where


parseJSON (Object v) = Payload <$> v .: "from"
<*> v .: "to"
<*> v .: "subject"
<*> v .: "body"
<*> v .: "offset_seconds"
parseJSON v = typeMismatch "Payload" v
$)"15&3  .0/"%4 (0/& 8*-% 

5IJT JT UIF TBNF BT UIF +40/ CVU GPS $47 EBUB

parseRecord :: Record -> Parser a

instance FromRecord Release where


parseRecord v
| V.length v == 5 = Release <$> v .! 0
<*> v .! 1
<*> v .! 2
<*> v .! 3
<*> v .! 4
| otherwise = mzero

5IJT POF VTFT liftA2 UP MJǒ UIF UVQMF EBUB DPOTUSVDUPS PWFS
parseKey BOE parseValue UP HJWF LFZWBMVF QBJSJOHT :PV DBO TFF
UIF (<*) PQFSBUPS JO UIFSF BHBJO BT XFMM BMPOH XJUI UIF JOƶY
PQFSBUPS GPS fmap BOE =<< BT XFMM
$)"15&3  .0/"%4 (0/& 8*-% 

instance Deserializeable ShowInfoResp where


parser = e2err =<< convertPairs . HM.fromList <$> parsePairs
where
parsePairs :: Parser [(Text, Text)]
parsePairs = parsePair `sepBy` endOfLine

parsePair = liftA2 (,) parseKey parseValue


parseKey = takeTill (==':') <* kvSep

kvSep = string ": "

parseValue = takeTill isEndOfLine

5IJT POF JOTUBODF JT B WJSUVBM DPSOVDPQJB PG BQQMJDBUJPOT


PG UIF QSFWJPVT DIBQUFST BOE XF CFMJFWF JU EFNPOTUSBUFT IPX
NVDI DMFBOFS BOE NPSF SFBEBCMF UIFTF DBO NBLF ZPVS DPEF

"OE OPX GPS TPNFUIJOH EJƵFSFOU


5IJT OFYU FYBNQMF JT BMTP VTJOH BO BQQMJDBUJWF CVU UIJT JT B CJU
EJƵFSFOU UIBO UIF BCPWF FYBNQMFT 8FƊMM TQFOE NPSF UJNF
FYQMBJOJOH UIJT POF BT UIJT QBUUFSO GPS XSJUJOH VUJMJUZ GVODUJPOT
JT DPNNPO
$)"15&3  .0/"%4 (0/& 8*-% 

module Web.Shipping.Utils ((<||>)) where

import Control.Applicative (liftA2)

(<||>) :: (a -> Bool) -> (a -> Bool) -> a -> Bool


(<||>) = liftA2 (||)

"U ƶSTU HMBODF UIJT EPFTOƊU TFFN UPP IBSE UP VOEFSTUBOE


CVU TPNF FYBNQMFT XJMM IFMQ ZPV EFWFMPQ BO VOEFSTUBOEJOH
PG XIBUƊT HPJOH PO 8F TUBSU XJUI UIF PQFSBUPS GPS CPPMFBO
EJTKVODUJPO (||) XIJDI JT BO PS

Prelude> True || False


True
Prelude> False || False
False
Prelude> (2 > 3) || (3 == 3)
True

"OE OPX XF XBOU UP CF BCMF UP LFFQ UIBU BT BO JOƶY PQFSBUPS


CVU MJǒ JU PWFS TPNF DPOUFYU TP XF VTF liftA2

Prelude> import Control.Applicative


Prelude> let (<||>) = liftA2 (||)

"OE XFƊMM NBLF TPNF USJWJBM GVODUJPOT BHBJO GPS UIF QVSQPTFT
PG EFNPOTUSBUJPO
$)"15&3  .0/"%4 (0/& 8*-% 

Prelude> let f 9001 = True; f _ = False


Prelude> let g 42 = True; g _ = False
Prelude> :t f
f :: (Eq a, Num a) => a -> Bool
Prelude> f 42
False
Prelude> f 9001
True
Prelude> g 42
True
Prelude> g 9001
False

8F DBO DPNQPTF UIF UXP GVODUJPOT ԕ BOE Ԗ UP UBLF POF JOQVU


BOE HJWF POF TVNNBSZ SFTVMU MJLF UIJT

Prelude> (\n -> f n || g n) 0


False
Prelude> (\n -> f n || g n) 9001
True
Prelude> :t (\n -> f n || g n)
(\n -> f n || g n) :: (Eq a, Num a) => a -> Bool

#VU XF IBWF UP QBTT JO UIBU BSHVNFOU ԝ JO PSEFS UP EP JU UIBU


XBZ 0VS VUJMJUZ GVODUJPO HJWFT VT B DMFBOFS XBZ

Prelude> (f <||> g) 0
$)"15&3  .0/"%4 (0/& 8*-% 

False
Prelude> (f <||> g) 9001
True

*UƊT QBSBMMFM BQQMJDBUJPO PG UIF GVODUJPOT BHBJOTU BO BSHVNFOU


5IBU BQQMJDBUJPO QSPEVDFT UXP WBMVFT TP XF NPOPJEBMMZ DPN
CJOF UIF UXP WBMVFT TP UIBU XF IBWF B TJOHMF WBMVF UP SFUVSO
8FƊWF TFU VQ BO FOWJSPONFOU TP UIBU UXP (a -> Bool) GVODUJPOT
UIBU EPOƊU IBWF BO Ԑ BSHVNFOU ZFU DBO SFUVSO B SFTVMU CBTFE PO
UIPTF UXP Bool WBMVFT XIFO UIF DPNCJOFE GVODUJPO JT FWFOUV
BMMZ BQQMJFE BHBJOTU BO Ԑ

 .POBE
#FDBVTF FƵFDUGVM QSPHSBNNJOH JT DPOTUSBJOFE JO )BTLFMM UISPVHI
UIF VTF PG IO BOE IO JT BO JOTUBODF PG .POBE FYBNQMFT PG
.POBE JO QSBDUJDBM )BTLFMM DPEF BSF FWFSZXIFSF 8F USJFE UP
ƶOE TPNF FYBNQMFT UIBU JMMVTUSBUF EJƵFSFOU JOUFSFTUJOH VTF
DBTFT

0QFOJOH B OFUXPSL TPDLFU


)FSF XFƊSF VTJOH do TZOUBY GPS IOƊT .POBE JO PSEFS UP CJOE B
TPDLFU IBOEMF GSPN UIF socket TNBSU DPOTUSVDUPS DPOOFDU JU
UP BO BEESFTT UIFO SFUVSO UIF IBOEMF GPS SFBEJOH BOE XSJUJOH
5IJT FYBNQMF JT GSPN haproxy-haskell BMTP CZ .JDIBFM 9BWJFS
4FF UIF network MJCSBSZ PO )BDLBHF GPS VTF BOE EPDVNFOUBUJPO
$)"15&3  .0/"%4 (0/& 8*-% 

import Network.Socket

openSocket :: FilePath -> IO Socket


openSocket p = do
sock <- socket AF_UNIX Stream defaultProtocol
connect sock sockAddr
return sock
where sockAddr = SockAddrUnix . encodeString $ p

5IJT JTOƊU UPP VOMJLF BOZUIJOH ZPV TBX JO QSFWJPVT DIBQUFST


GSPN UIF IBOHNBO HBNF UP UIF .POBE DIBQUFS 5IF OFYU
FYBNQMF JT B CJU SJDIFS

#JOEJOH PWFS GBJMVSF JO JOJUJBMJ[BUJPO


.JDIBFM 9BWJFSƊT 4FSBQI JT B QSPDFTT NPOJUPS BOE IBT B main
GVODUJPO XIJDI JT UZQJDBM PG NPSF EFWFMPQFE MJCSBSJFT BOE
BQQMJDBUJPOT 5IF PVUFSNPTU .POBE JT KVTU IO CVU UIF NPOBE
USBOTGPSNFS WBSJBOU PG Either DBMMFE EitherT JT VTFE UP CJOE
PWFS UIF QPTTJCJMJUZ PG GBJMVSF JO DPOTUSVDUJOH BO JOJUJBMJ[BUJPO
GVODUJPO 5IJT QPTTJCJMJUZ PG GBJMVSF DFOUFST PO CFJOH BCMF UP
QVMM VQ B DPSSFDU DPOƶHVSBUJPO
$)"15&3  .0/"%4 (0/& 8*-% 

main :: IO ()
main = do
initAndFp <- runEitherT $ do
fp <- tryHead NoConfig =<< lift getArgs
initCfg <- load' fp
return (initCfg, fp)
either bail (uncurry boot) initAndFp
where
boot initCfg fp =
void $ runMVC mempty
oracleModel (core initCfg fp)
bail NoConfig =
errorExit "Please pass a config"
bail (InvalidConfig e) =
errorExit ("Invalid config " ++ show e)
load' fp =
hoistEither
. fmapL InvalidConfig =<< lift (load fp)

*G ZPV GPVOE UIBU WFSZ EFOTF BOE EJƸDVMU UP GPMMPX BU UIJT


QPJOU XFƊE FODPVSBHF ZPV UP IBWF BOPUIFS MPPL BU JU BǒFS XFƊWF
DPWFSFE NPOBE USBOTGPSNFST
$)"15&3  .0/"%4 (0/& 8*-% 

 "O FOEUPFOE FYBNQMF 63-


TIPSUFOFS
*O UIJT TFDUJPO XFƊSF HPJOH UP XBML UISPVHI BO FOUJSF QSPHSBN
CFHJOOJOH UP FOE 5IFSF BSF TPNF QJFDFT XF BSF OPU HPJOH
UP FYQMBJO UIPSPVHIMZ IPXFWFS UIJT JT TPNFUIJOH ZPV DBO
BDUVBMMZ CVJME BOE XPSL XJUI JG ZPVƊSF JOUFSFTUFE JO EPJOH TP
'JSTU UIF $BCBM ƶMF GPS UIF QSPKFDU

name: shawty
version: 0.1.0.0
synopsis: Initial project template from stack
description: Please see README.md
homepage: http://github.com/bitemyapp/shawty
license: BSD3
license-file: LICENSE
author: Chris Allen
maintainer: [email protected]
copyright: 2015, Chris Allen
category: Web
build-type: Simple
cabal-version: >=1.10

executable shawty

5IF DPEF JO UIJT FYBNQMF DBO CF GPVOE IFSF https://github.com/bitemyapp/
shawty-prime/blob/master/app/Main.hs
$)"15&3  .0/"%4 (0/& 8*-% 

hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, bytestring
, hedis
, mtl
, network-uri
, random
, scotty
, semigroups
, text
, transformers
default-language: Haskell2010

"OE UIF QSPKFDU MBZPVU

$ tree
.
├── LICENSE
├── Setup.hs
├── app
│   └── Main.hs
├── shawty.cabal
└── stack.yaml
$)"15&3  .0/"%4 (0/& 8*-% 

:PV NBZ DIPPTF UP VTF 4UBDL PS OPU 5IBU JT IPX XF HPU UIF
UFNQMBUF GPS UIF QSPKFDU JO QMBDF *G ZPVƊE MJLF UP MFBSO NPSF
DIFDL PVU 4UBDLƊT (JUIVC SFQP BOE UIF 4UBDL WJEFP UVUPSJBM
XF XPSLFE PO UPHFUIFS 5IF DPEF GPMMPXJOH GSPN UIJT QPJOU JT
JO Main.hs
8F OFFE UP TUBSU PVS QSPHSBN PƵ XJUI B MBOHVBHF FYUFOTJPO

{-# LANGUAGE OverloadedStrings #-}

0WFSMPBEFE4USJOHT JT B XBZ UP NBLF String MJUFSBMT QPMZ


NPSQIJD UIF XBZ OVNFSJD MJUFSBMT BSF QPMZNPSQIJD PWFS UIF
Num UZQFDMBTT String MJUFSBMT BSF OPU PSEJOBSJMZ QPMZNPSQIJD
String JT B DPODSFUF UZQF 6TJOH 0WFSMPBEFE4USJOHT BMMPXT VT
UP VTF TUSJOH MJUFSBMT BT Text BOE ByteString WBMVFT

#SJFG BTJEF BCPVU QPMZNPSQIJD MJUFSBMT


8F NFOUJPOFE UIBU UIF JOUFHSBM OVNCFS MJUFSBMT JO )BTLFMM
BSF UZQFE Num a => a CZ EFGBVMU /PX UIBU XF IBWF BOPUIFS
FYBNQMF UP XPSL XJUI JUƊT XPSUI FYBNJOJOH IPX UIFZ XPSL
VOEFS UIF IPPE TP UP TQFBL 'JSTU MFUƊT MPPL BU B UZQFDMBTT GSPN
B NPEVMF JO base

Prelude> import Data.String



4UBDL (JUIVC SFQP https://github.com/commercialhaskell/stack

5IF WJEFP 4UBDL NFHBUVUPSJBM 5IF XIPMF WJEFP JT MPOH CVU DPWFST B MPU PG BCOPSNBM
VTF DBTFT 6TF UIF UJNF TUBNQT UP KVNQ UP XIBU ZPV OFFE UP MFBSO https://www.youtube.
com/watch?v=sRonIB8ZStw&feature=youtu.be
$)"15&3  .0/"%4 (0/& 8*-% 

Prelude> :info IsString


class IsString a where
fromString :: String -> a
-- Defined in ‘Data.String’
instance IsString [Char] -- Defined in ‘Data.String’

5IFO XF NBZ OPUJDF TPNFUIJOH JO Num BOE Fractional

class Num a where


-- irrelevant bits elided
fromInteger :: Integer -> a

class Num a => Fractional a where


-- Elision again
fromRational :: Rational -> a

0LBZ BOE XIBU BCPVU PVS MJUFSBMT

Prelude> :set -XOverloadedStrings


Prelude> :t 1
1 :: Num a => a
Prelude> :t 1.0
1.0 :: Fractional a => a
Prelude> :t "blah"
"blah" :: IsString a => a
$)"15&3  .0/"%4 (0/& 8*-% 

5IF CBTJD EFTJHO JT UIBU UIF VOEFSMZJOH SFQSFTFOUBUJPO JT


DPODSFUF CVU ()$ BVUPNBUJDBMMZ XSBQT JU JO fromStringfromIntegerf
4P JUƊT BT JG

{-# LANGUAGE OverloadedStrings #-}

"blah" :: Text == fromString ("blah" :: String)

1 :: Int == fromInteger (1 :: Integer)

2.5 :: Double == fromRational (2.5 :: Rational)

-JCSBSJFT MJLF text BOE bytestring QSPWJEF JOTUBODFT GPS IsString


JO PSEFS UP QFSGPSN UIF DPOWFSTJPO "TTVNJOH ZPV IBWF UIPTF
MJCSBSJFT JOTUBMMFE ZPV DBO LJDL JU BSPVOE B MJUUMF /PUF UIBU
EVF UP UIF NPOPNPSQIJTN SFTUSJDUJPO UIF GPMMPXJOH XJMM XPSL
JO UIF 3&1- CVU XPVME OPU XPSL JG XF MPBEFE JU GSPN B TPVSDF
ƶMF CFDBVTF JU XPVME EFGBVMU UP B DPODSFUF UZQF XFƊWF TFFO
UIJT B DPVQMF UJNFT FBSMJFS JO UIF CPPL


Prelude> :set -XOverloadedStrings


Prelude> let a = "blah"
Prelude> a
"blah"
Prelude> :t a
a :: Data.String.IsString a => a
$)"15&3  .0/"%4 (0/& 8*-% 

5IFO ZPV DBO NBLF JU B Text PS ByteString WBMVF

Prelude> import Data.Text (Text)


Prelude> import Data.ByteString (ByteString)
Prelude> let t = "blah" :: Text
Prelude> let bs = "blah" :: ByteString
Prelude> t == bs

Couldn't match expected type ‘Text’ with


actual type ‘ByteString’
In the second argument of ‘(==)’, namely ‘bs’
In the expression: t == bs

0WFSMPBEFE4USJOHT JT B DPOWFOJFODF UIBU PSJHJOBUFE JO UIF


EFTJSF PG XPSLJOH )BTLFMM QSPHSBNNFST UP VTF TUSJOH MJUFSBMT
GPS Text BOE ByteString WBMVFT *UƊT OPU UPP CJH B EFBM CVU JU
DBO CF OJDF BOE TBWFT ZPV NBOVBMMZ XSBQQJOH FBDI MJUFSBM JO
ƌGSPN4USJOHƍ

#BDL UP UIF TIPX


/FYU UIF NPEVMF OBNF NVTU CF Main BT UIBU JT SFRVJSFE GPS
BOZUIJOH FYQPSUJOH B main GVODUJPO UP CF JOWPLFE XIFO UIF
FYFDVUBCMF SVOT 8F GPMMPX UIF 0WFSMPBEFE4USJOHT FYUFOTJPO
XJUI PVS JNQPSUT
$)"15&3  .0/"%4 (0/& 8*-% 

module Main where

import Control.Monad (replicateM)


import Control.Monad.IO.Class (liftIO)
import qualified Data.ByteString.Char8 as BC
import Data.Text.Encoding (decodeUtf8, encodeUtf8)
import qualified Data.Text.Lazy as TL
import qualified Database.Redis as R
import Network.URI (URI, parseURI)
import qualified System.Random as SR
import Web.Scotty

8IFSF XF JNQPSU TPNFUIJOH ƌRVBMJƶFE ƒ


BT ƒ
ƍ XF BSF
EPJOH UXP UIJOHT 2VBMJGZJOH UIF JNQPSU NFBOT UIBU XF DBO
POMZ SFGFS UP WBMVFT JO UIF NPEVMF XJUI UIF GVMM NPEVMF QBUI
BOE XF VTF ƌBTƍ UP HJWF UIF NPEVMF UIBU XF XBOU JO TDPQF B
OBNF 'PS FYBNQMF Data.ByteString.Char8.pack JT B GVMMZ RVBMJ
ƶFE SFGFSFODF UP pack 8F RVBMJGZ UIF JNQPSU TP UIBU XF EPOƊU
JNQPSU EFDMBSBUJPOT UIBU XPVME DPOƷJDU XJUI CJOEJOHT UIBU BM
SFBEZ FYJTU JO 1SFMVEF #Z TQFDJGZJOH B OBNF VTJOH ƌBT ƍ XF
DBO HJWF UIF WBMVF B TIPSUFS NPSF DPOWFOJFOU OBNF 8IFSF
XF JNQPSU UIF NPEVMF OBNF GPMMPXFE CZ QBSFOUIFTFT TVDI
BT XJUI replicateM PS liftIO XF BSF TBZJOH XF POMZ XBOU UP JN
QPSU UIF GVODUJPOT PS WBMVFT PG UIBU OBNF BOE OPUIJOH FMTF
*O UIF DBTF PG import Web.Scotty XF BSF JNQPSUJOH FWFSZUIJOH
8FC4DPUUZ FYQPSUT "O VORVBMJƶFE BOE VOTQFDJƶD JNQPSU
$)"15&3  .0/"%4 (0/& 8*-% 

TIPVME CF BWPJEFE FYDFQU JO UIPTF DBTFT XIFSF UIF QSPWFOBODF


PG UIF JNQPSUFE GVODUJPOT XJMM CF PCWJPVT PS XIFO UIF JNQPSU
JT B UPPMLJU ZPV NVTU VTF BMM UPHFUIFS TVDI BT 4DPUUZ
/FYU XF OFFE UP HFOFSBUF PVS TIPSUFOFE 63-T UIBU XJMM SFGFS
UP UIF MJOLT QFPQMF QPTU UP UIF TFSWJDF 8F XJMM NBLF B 4USJOH
PG UIF DIBSBDUFST XF XBOU UP TFMFDU GSPN

alphaNum :: String
alphaNum = ['A'..'Z'] ++ ['0'..'9']

/PX XF OFFE UP QJDL SBOEPN FMFNFOUT GSPN alphaNum 5IF


HFOFSBM JEFB IFSF TIPVME CF GBNJMJBS GSPN UIF )BOHNBO HBNF
'JSTU XF ƶOE UIF MFOHUI PG UIF MJTU UP EFUFSNJOF B SBOHF UP
TFMFDU GSPN UIFO HFU B SBOEPN OVNCFS JO UIBU SBOHF VTJOH IO
UP IBOEMF UIF SBOEPNOFTT

randomElement :: String -> IO Char


randomElement xs = do
let maxIndex :: Int
maxIndex = length xs - 1
-- Right of arrow is IO Int, so randomDigit is Int
randomDigit <- SR.randomRIO (0, maxIndex) :: IO Int
return (xs !! randomDigit)

/FYU XF BQQMZ randomElement UP alphaNum UP HFU B TJOHMF SBO


EPN MFUUFS PS OVNCFS GSPN PVS BMQIBCFU 5IFO XF VTF replicateM
$)"15&3  .0/"%4 (0/& 8*-% 

7 UP SFQFBU UIJT BDUJPO  UJNFT HJWJOH B MJTU PG  SBOEPN MFUUFST


PS OVNCFST

shortyGen :: IO [Char]
shortyGen = replicateM 7 (randomElement alphaNum)

'PS BEEJUJPOBM GVO TFF XIBU replicateM 2 [1, 3] EPFT BOE


XIFUIFS ZPV DBO ƶHVSF PVU XIZ $PNQBSF JU UP UIF 1SFMVEF
GVODUJPO replicate
:PV NBZ IBWF OPUJDFE B NFOUJPO PG 3FEJT JO PVS JNQPSUT
BOE XPOEFSFE XIBU XBT VQ *G ZPVƊSF OPU BMSFBEZ GBNJMJBS XJUI
JU 3FEJT JT JONFNPSZ LFZWBMVF EBUB TUPSBHF 5IF EFUBJMT
PG IPX 3FEJT XPSLT BSF XFMM CFZPOE UIF TDPQF PG UIJT CPPL
BOE UIFZƊSF OPU WFSZ JNQPSUBOU IFSF 3FEJT DBO CF DPOWFOJFOU
GPS TPNF DPNNPO VTF DBTFT MJLF DBDIJOH PS XIFO ZPV XBOU
QFSTJTUFODF XJUIPVU B MPU PG DFSFNPOZ BT XBT UIF DBTF IFSF
:PV XJMM OFFE UP JOTUBMM BOE IBWF 3FEJT SVOOJOH JO PSEFS GPS
UIF QSPKFDU UP XPSL PUIFSXJTF UIF XFC TFSWFS XJMM UISPX BO
FSSPS VQPO GBJMJOH UP DPOOFDU UP 3FEJT
5IJT OFYU CJU JT B GVODUJPO XIPTF BSHVNFOUT BSF PVS DPO
OFDUJPO UP 3FEJT R.Connection
UIF LFZ XF BSF TFUUJOH JO 3FEJT
BOE UIF WBMVF XF BSF TFUUJOH UIF LFZ UP 8F BMTP QFSGPSN TJEF
FƵFDUT JO IO UP HFU Either R.Reply R.Status BT B SFTVMU 5IF LFZ
JO UIJT DBTF JT UIF SBOEPNMZ HFOFSBUFE 63* XF DSFBUFE BOE
UIF WBMVF JT UIF 63- UIF VTFS XBOUT UIF TIPSUFOFS UP QSPWJEF
BU UIBU BEESFTT
$)"15&3  .0/"%4 (0/& 8*-% 

saveURI :: R.Connection
-> BC.ByteString
-> BC.ByteString
-> IO (Either R.Reply R.Status)
saveURI conn shortURI uri =
R.runRedis conn $ R.set shortURI uri

5IF OFYU GVODUJPO getURI UBLFT UIF DPOOFDUJPO UP 3FEJT BOE


UIF TIPSUFOFE 63* LFZ JO PSEFS UP HFU UIF 63* BTTPDJBUFE XJUI
UIBU TIPSU 63- BOE TIPX VTFST XIFSF UIFZƊSF IFBEFE

getURI :: R.Connection
-> BC.ByteString
-> IO (Either R.Reply (Maybe BC.ByteString))
getURI conn shortURI = R.runRedis conn $ R.get shortURI

/FYU TPNF CBTJD UFNQMBUJOH GVODUJPOT GPS SFUVSOJOH PVUQVU


UP UIF XFC CSPXTFS

linkShorty :: String -> String


linkShorty shorty =
concat [ "<a href=\""
, shorty
, "\">Copy and paste your short URL</a>"
]
$)"15&3  .0/"%4 (0/& 8*-% 

5IF ƶOBM PVUQVU UP 4DPUUZ IBT UP CF B Text WBMVF TP XFƊSF


DPODBUFOBUJOH MJTUT PG Text WBMVFT UP QSPEVDF SFTQPOTFT UP UIF
CSPXTFS

-- TL.concat :: [TL.Text] -> TL.Text


shortyCreated :: Show a => a -> String -> TL.Text
shortyCreated resp shawty =
TL.concat [ TL.pack (show resp)
, " shorty is: ", TL.pack (linkShorty shawty)
]

shortyAintUri :: TL.Text -> TL.Text


shortyAintUri uri =
TL.concat [ uri
, " wasn't a url, did you forget http://?"
]

shortyFound :: TL.Text -> TL.Text


shortyFound tbs =
TL.concat ["<a href=\"", tbs, "\">", tbs, "</a>"]

/PX XF HFU UP UIF CVML PG XFCBQQZ CJUT JO UIF GPSN PG PVS


BQQMJDBUJPO 8FƊMM FOVNFSBUF UIF BQQMJDBUJPO JO DIVOLT CVU
UIFZƊSF BMM JO POF app GVODUJPO
$)"15&3  .0/"%4 (0/& 8*-% 

app :: R.Connection
-> ScottyM ()
app rConn = do
-- [1]
get "/" $ do
-- [2]
uri <- param "uri"
-- [3]

 3FEJT DPOOFDUJPO UIBU TIPVMEƊWF CFFO ƶSFE VQ CFGPSF UIF


XFC TFSWFS TUBSUFE

 get JT B GVODUJPO UIBU UBLFT B RoutePattern BO BDUJPO UIBU


SFUVSOT BO )551 SFTQPOTF BOE BEET UIF SPVUF UP UIF
4DPUUZ TFSWFS JUƊT FNCFEEFE JO "T ZPV NJHIU TVTQFDU
RoutePattern IBT BO IsString JOTUBODF TP UIBU UIF QBUUFSO
DBO CF B TUSJOH MJUFSBM 5IF UPQMFWFM SPVUF JT FYQSFTTFE BT
ƍƍ JF MJLF HPJOH UP https://google.com/ PS https://bitemyapp.
com/ 5IBU ƶOBM / DIBSBDUFS JT XIBUƊT CFJOH FYQSFTTFE

 5IF param GVODUJPO JT B NFBOT PG HFUUJOHƒQBSBNFUFST

param :: Parsable a => Data.Text.Internal.Lazy.Text


-> ActionM a

*UƊT TPSU PG MJLF Read CVU JUƊT QBSTJOH B WBMVF PG UIF UZQF
ZPV BTL GPS 5IF param GVODUJPO DBO ƶOE BSHVNFOUT WJB
$)"15&3  .0/"%4 (0/& 8*-% 

63- QBUI DBQUVSFT TFF CFMPX XJUI :short


)5.- GPSN
JOQVUT PS RVFSZ QBSBNFUFST 5IF ƶSTU BSHVNFOU UP param
JT UIF ƌOBNFƍ PS LFZ GPS UIF JOQVU 8F DBOOPU FYQMBJO UIF
FOUJSFUZ PG )551 BOE )5.- IFSF CVU UIF GPMMPXJOH BSF
NFBOT PG HFUUJOH B QBSBN XJUI UIF LFZ ƌOBNFƍ

B
63- QBUI DBQUVSF

get "/user/:name/view" $ do

-- requesting the URL /user/Blah/view would make name = "B


-- such as: http://localhost:3000/user/Blah/view
C
)5.- JOQVU GPSN )FSF UIF OBNF BUUSJCVUF GPS UIF
JOQVU ƶFME JT ƍOBNFƍ

<form>
Name:<br>
<input type="text" name="name">
</form>

D
2VFSZ QBSBNFUFST GPS 63*T BSF QBJSJOHT PG LFZT BOE
WBMVFT GPMMPXJOH B RVFTUJPO NBSL

http://localhost:3000/?name=Blah

:PV DBO EFƶOF NPSF UIBO POF CZ VTJOH BNQFSTBOE UP


TFQBSBUF UIF LFZ WBMVF QBJST

http://localhost:3000/?name=Blah&state=Texas
$)"15&3  .0/"%4 (0/& 8*-% 

/PX GPS UIF OFYU DIVOL PG UIF app GVODUJPO

let parsedUri :: Maybe URI


parsedUri = parseURI (TL.unpack uri)
case parsedUri of
-- [1]
Just _ -> do
shawty <- liftIO shortyGen
-- [2]
let shorty = BC.pack shawty
-- [3]
uri' = encodeUtf8 (TL.toStrict uri)
-- [4]
resp <- liftIO (saveURI rConn shorty uri')
-- [5]
html (shortyCreated resp shawty)
-- [6]
Nothing -> text (shortyAintUri uri)
-- [7]

 8F UFTU UIBU UIF VTFS HBWF VT B WBMJE 63* CZ VTJOH UIF


network-uri MJCSBSZƊT parseURI GVODUJPO 8F EPOƊU SFBMMZ
DBSF BCPVU UIF EBUBUZQF JU HPU XSBQQFE JO TP XIFO XF
DIFDL JG JUƊT +VTU PS /PUIJOH XF ESPQ JU PO UIF ƷPPS

 5IF Monad IFSF JT ActionM BO BMJBT PG ActionT


XIJDI JT B
$)"15&3  .0/"%4 (0/& 8*-% 

EBUBUZQF SFQSFTFOUJOH DPEF UIBU IBOEMFT XFC SFRVFTUT


BOE SFUVSOT SFTQPOTFT :PV DBO QFSGPSN IO BDUJPOT JO
UIJT .POBE CVU ZPV IBWF UP MJǒ UIF IO BDUJPO PWFS UIF
BEEJUJPOBM TUSVDUVSF $POWFOUJPOBMMZ POF VTFT MonadIO BT B
TPSU PG BVUPMJǒ GPS IO BDUJPOT CVU ZPV DPVME EP JU NBOVBMMZ
8F XPOƊU EFNPOTUSBUF UIJT IFSF 8F XJMM FYQMBJO NPOBE
USBOTGPSNFST JO B MBUFS DIBQUFS TP UIBU ActionT XJMM CF MFTT
NZTUFSJPVT

 $POWFSUJOH UIF TIPSU DPEF GPS UIF 63* JOUP B $IBS CZUFTUSJOH
GPS TUPSBHF JO 3FEJT

 $POWFSUJOH UIF 63* UIF VTFS QSPWJEFE GSPN B MB[Z Text


WBMVF JOUP B TUSJDU Text WBMVF UIFO FODPEJOH BT B 65' B
DPNNPO VOJDPEF GPSNBU
#ZUF4USJOH GPS TUPSBHF JO 3FEJT

 "HBJO VTJOH liftIO TP UIBU XF DBO QFSGPSN BO IO BDUJPO


JOTJEF B 4DPUUZ ActionM *O UIJT DBTF XFƊSF TBWJOH UIF TIPSU
DPEF BOE UIF 63* JO 3FEJT TP UIBU XF DBO MPPL UIJOHT VQ
XJUI UIF TIPSU DPEF BT B LFZ UIFO HFU UIF 63* CBDL BT B
WBMVF JG JU IBT CFFO TUPSFE JO UIF QBTU

 5IF UFNQMBUFE SFTQPOTF XF SFUVSO XIFO XF TVDDFTTGVMMZ


TBWFE UIF TIPSU DPEF GPS UIF 63* 5IJT HJWFT UIF VTFS B
TIPSUFOFE 63* UP TIBSF

 &SSPS SFTQPOTF JO DBTF UIF VTFS HBWF VT B 63* UIBU XBTOƊU


WBMJE
$)"15&3  .0/"%4 (0/& 8*-% 

5IF TFDPOE IBOEMFS IBOEMFT SFRVFTUT UP B TIPSUFOFE 63*


BOE SFUVSOT UIF VOTIPSUFOFE 63- UP GPMMPX

get "/:short" $ do
-- [1]
short <- param "short"
-- [2]
uri <- liftIO (getURI rConn short)
-- [3]
case uri of
Left reply -> text (TL.pack (show reply))
-- [4] [5]
Right mbBS -> case mbBS of
-- [6]
Nothing -> text "uri not found"
-- [7]
Just bs -> html (shortyFound tbs)
-- [8]
where tbs :: TL.Text
tbs = TL.fromStrict (decodeUtf8 bs)
-- [9]

 5IJT JT UIF 63- QBUI DBQUVSF XF NFOUJPOFE FBSMJFS TVDI


UIBU SFRVFTUJOH /blah GSPN UIF TFSWFS XJMM DBVTF JU UP HFU
UIF LFZ ƌCMBIƍ GSPN 3FEJT BOE JG UIFSFƊT B WBMVF TUPSFE JO
UIBU LFZ SFUVSO UIBU 63* JO UIF SFTQPOTF 5P EP UIBU JO B
$)"15&3  .0/"%4 (0/& 8*-% 

XFC CSPXTFS PS XJUI DVSMXHFU ZPVƊE QPJOU ZPVS DMJFOU BU


http://localhost:3000/blah UP UFTU JU

 4BNF QBSBN GFUDIJOH BT CFGPSF 5IJT UJNF XF FYQFDU JU UP


CF QBSU PG UIF QBUI DBQUVSF SBUIFS UIBO B RVFSZ BSHVNFOU

 -JǒJOH BO *0 BDUJPO JOTJEF "DUJPO. BHBJO UIJT UJNF UP HFU


UIF TIPSU DPEF BT UIF MPPLVQ LFZ GSPN 3FEJT

 -Fǒ IFSF JO UIF &JUIFS XF HFU CBDL GSPN 3FEJT


TJHOJƶFT
TPNF LJOE PG GBJMVSF VTVBMMZ BO FSSPS

 5FYU SFTQPOTF SFUVSOJOH BO FSSPS JO DBTF XF HPU -Fǒ TP UIBU


UIF VTFS LOPXT XIBU UIF FSSPS XBT UBLJOH BEWBOUBHF PG
3FEJT IBWJOH 4IPXBCMF FSSPST UP SFOEFS JU JO UIF SFTQPOTF

 )BQQZ QBUI

 +VTU CFDBVTF BO FSSPS EJEOƊU IBQQFO EPFTOƊU NFBO UIF LFZ


XBT JO UIF EBUBCBTF

 8F GFUDI B LFZ UIBU FYJTUT JO UIF EBUBCBTF HFU UIF CZUFTUSJOH


PVU PG UIF +VTU EBUB DPOTUSVDUPS BOE SFOEFS UIF 63* JO UIF
TVDDFTT UFNQMBUF UP TIPX UIF VTFS UIF 63* XF TUPSFE

 (PJOH JO UIF PQQPTJUF EJSFDUJPO XF XFOU JO CFGPSF ƈ EF


DPEJOH UIF #ZUF4USJOH PO UIF BTTVNQUJPO JUƊT FODPEFE BT
65' UIFO DPOWFSUJOH GSPN B TUSJDU 5FYU WBMVF UP B MB[Z
5FYU WBMVF
$)"15&3  .0/"%4 (0/& 8*-% 

/PX XF DPNF UP UIF main FWFOU 0VS main GVODUJPO SFUVSOT IO


() BOE BDUT BT UIF FOUSZ QPJOU GPS PVS XFCTFSWFS XIFO XF TUBSU
UIF FYFDVUBCMF 8F CFHJO CZ JOWPLJOH scotty 3000 B IFMQFS
GVODUJPO GSPN UIF 4DPUUZ GSBNFXPSL XIJDI HJWFO B QPSU UP
SVO PO BOE B 4DPUUZ BQQMJDBUJPO XJMM MJTUFO GPS SFRVFTUT BOE
SFTQPOE UP UIFN

main :: IO ()
main = do
rConn <- R.connect R.defaultConnectInfo
scotty 3000 (app rConn)

"OE UIBU JT UIF FOUJSFUZ PG UIJT 63- TIPSUFOFS 8F IBWF B


DPVQMF PG FYFSDJTFT CBTFE PO UIJT DPEF BOE XF FODPVSBHF ZPV
UP DPNF CBDL UP JU BǒFS XFƊWF DPWFSFE NPOBE USBOTGPSNFST BT
XFMM BOE TFF IPX ZPVS DPNQSFIFOTJPO JT HSPXJOH

&YFSDJTF
*O UIF 63- TIPSUFOFS BO JNQPSUBOU TUFQ XBT PNJUUFE 8FƊSF
OPU DIFDLJOH JG XFƊSF PWFSXSJUJOH BO FYJTUJOH TIPSU DPEF XIJDI
JT FOUJSFMZ QPTTJCMF EFTQJUF UIFN CFJOH SBOEPNMZ HFOFSBUFE
8F DBO BDUVBMMZ DBMDVMBUF UIF PEET PG UIJT CZ FYBNJOJOH UIF
DBSEJOBMJUZ PG UIF WBMVFT
$)"15&3  .0/"%4 (0/& 8*-% 

-- alphaNum = ['A'..'Z'] ++ ['0'..'9']


-- shortyGen =
-- replicateM 7 (randomElement alphaNum)

length alphaNum ^ 7 == 78364164096

4P UIF QSPCMFN JT XIBU JG XF BDDJEFOUBMMZ DMPCCFS B QSFWJ


PVTMZ HFOFSBUFE TIPSU 63* 5IFSF BSF B GFX XBZT PG TPMWJOH
UIJT 0OF JT UP DIFDL UP TFF JG UIF TIPSU 63* BMSFBEZ FYJTUT JO UIF
EBUBCBTF CFGPSF TBWJOH JU BOE UISPXJOH BO FSSPS JG JU EPFT 5IJT
JT HPJOH UP CF WBOJTIJOHMZ VOMJLFMZ UP IBQQFO VOMFTT ZPVƊWF
TVEEFOMZ CFDPNF B WFSZ QPQVMBS 63* TIPSUFOJOH TFSWJDF CVU
JUƊE QSFWFOU UIF MPTT PG BOZ EBUB :PVS FYFSDJTF JT UP EFWJTF
TPNF NFBOT PG NBLJOH UIJT MFTT MJLFMZ 5IF FBTJFTU XBZ XPVME
CF UP TJNQMZ NBLF UIF TIPSU DPEFT MPOH FOPVHI UIBU ZPVƊE
OFFE UP SVO B DPNQVUFS VOUJM UIF IFBU EFBUI PG UIF VOJWFSTF
UP HFU B DPMMJTJPO CVU ZPV TIPVME USZ UISPXJOH BO FSSPS JO UIF
ƶSTU IBOEMFS XF TIPXFE ZPV ƶSTU

 5IBUƊT B XSBQ


8F IPQF UIJT DIBQUFS HBWF ZPV TPNF JEFB PG IPX )BTLFMMFST
VTF UIF UZQFDMBTTFT XFƊWF CFFO UBMLJOH BCPVU JO SFBM DPEF UP
IBOEMF WBSJPVT UZQFT PG QSPCMFNT *O UIF OFYU UXP DIBQUFST
XFƊMM CF MPPLJOH BU Foldable BOE Traversable UXP UZQFDMBTTFT
XJUI TPNF JOUFSFTUJOH QSPQFSUJFT UIBU SFMZ PO UIFTF GPVS BMHF
$)"15&3  .0/"%4 (0/& 8*-% 

CSBJD TUSVDUVSFT NPOPJE GVODUPS BQQMJDBUJWF BOE NPOBE



TP XF FODPVSBHF ZPV UP UBLF TPNF UJNF UP FYQMPSF TPNF PG
UIF VTFT XFƊWF EFNPOTUSBUFE IFSF $POTJEFS HPJOH CBDL UP
BOZUIJOH ZPV EJEOƊU VOEFSTUBOE WFSZ XFMM UIF ƶSTU UJNF ZPV
XFOU UISPVHI UIPTF DIBQUFST

 'PMMPXVQ SFTPVSDFT


 5IF DBTF PG UIF NZTUFSJPVT FYQMPTJPO JO TQBDF #SZBO
0Ɗ4VMMJWBO &YQMBJOT IPX ()$ IBOEMFT TUSJOH MJUFSBMT
$IBQUFS 

'PMEBCMF

:PV HPUUB LOPX XIFO UP


IPME ƊFN LOPX XIFO UP
GPME ƊFN LOPX XIFO UP
XBML BXBZ LOPX XIFO UP
SVO

,FOOZ 3PHFST


$)"15&3  '0-%"#-& 

 'PMEBCMF
5IJT UZQFDMBTT IBT CFFO BQQFBSJOH JO UZQF TJHOBUVSFT BU MFBTU
TJODF $IBQUFS  CVU GPS ZPVS QVSQPTFT JO UIPTF FBSMZ DIBQUFST
XF TBJE ZPV DPVME UIJOL PG B 'PMEBCMF UIJOH BT B MJTU "T ZPV
TBX JO UIF DIBQUFS PO GPMET MJTUT BSF DFSUBJOMZ GPMEBCMF EBUB
TUSVDUVSFT #VU JU JT BMTP USVF UIBU MJTUT BSF OPU UIF POMZ GPMEBCMF
EBUB TUSVDUVSFT TP UIJT DIBQUFS XJMM FYQBOE PO UIF JEFB PG
DBUBNPSQIJTNT BOE HFOFSBMJ[F JU UP NBOZ EBUBUZQFT
" MJTU GPME JT B XBZ UP SFEVDF UIF WBMVFT JOTJEF B MJTU UP POF
TVNNBSZ WBMVF CZ SFDVSTJWFMZ BQQMZJOH TPNF GVODUJPO *U JT
TPNFUJNFT EJƸDVMU UP BQQSFDJBUF UIBU BT ƶMUFSJOH BOE NBQQJOH
GVODUJPOT NBZ CF JNQMFNFOUFE JO UFSNT PG B GPME BOE ZFU
SFUVSO BO FOUJSFMZ OFX MJTU 5IF OFX MJTU JT UIF TVNNBSZ WBMVF
PG UIF PME MJTU BǒFS CFJOH SFEVDFE PS USBOTGPSNFE CZ GVODUJPO
BQQMJDBUJPO
5IF GPMEJOH GVODUJPO JT BMXBZT EFQFOEFOU PO TPNF .POPJE
JOTUBODF 5IF GPMET XF XSPUF QSFWJPVTMZ NPTUMZ SFMJFE PO
JNQMJDJU NPOPJEBM PQFSBUJPOT "T XFƊMM TFF JO UIJT DIBQUFS
HFOFSBMJ[JOH DBUBNPSQIJTNT UP PUIFS EBUBUZQFT EFQFOET PO
VOEFSTUBOEJOH UIF NPOPJET GPS UIPTF TUSVDUVSFT BOE JO TPNF
DBTFT NBLJOH UIFN FYQMJDJU
5IJT DIBQUFS XJMM DPWFS

Ƒ UIF 'PMEBCMF DMBTT BOE JUT DPSF PQFSBUJPOT

Ƒ UIF NPOPJEBM OBUVSF PG GPMEJOH


$)"15&3  '0-%"#-& 

Ƒ TUBOEBSE PQFSBUJPOT EFSJWFE GSPN GPMEJOH

 5IF 'PMEBCMF DMBTT


5IF )BDLBHF EPDVNFOUBUJPO GPS UIF 'PMEBCMF UZQFDMBTT EF
TDSJCFT JU BT CFJOH B ƌDMBTT PG EBUB TUSVDUVSFT UIBU DBO CF GPMEFE
UP B TVNNBSZ WBMVFƍ 5IF GPMEJOH PQFSBUJPOT UIBU XFƊWF TFFO
QSFWJPVTMZ ƶU OFBUMZ JOUP UIBU EFƶOJUJPO CVU UIJT UZQFDMBTT JO
DMVEFT NBOZ PQFSBUJPOT 8FƊSF HPJOH UP HP UISPVHI UIF GVMM
EFƶOJUJPO B MJUUMF BU B UJNF 5IF EFƶOJUJPO JO UIF MJCSBSZ CFHJOT

class Foldable t where


{-# MINIMAL foldMap | foldr #-}

5IF MINIMAL BOOPUBUJPO PO UIF UZQFDMBTT UFMMT ZPV UIBU B


NJOJNBMMZ DPNQMFUF EFƶOJUJPO PG UIF UZQFDMBTT XJMM EFƶOF
foldMap PS foldr GPS B EBUBUZQF "T JU IBQQFOT foldMap BOE foldr
DBO FBDI CF JNQMFNFOUFE JO UFSNT PG UIF PUIFS BOE UIF PUIFS
PQFSBUJPOT JODMVEFE JO UIF UZQFDMBTT DBO CF JNQMFNFOUFE JO
UFSNT PG FJUIFS PG UIFN "T MPOH BT BU MFBTU POF JT EFƶOFE ZPV
IBWF B XPSLJOH JOTUBODF PG 'PMEBCMF 4PNF NFUIPET JO UIF
UZQFDMBTT IBWF EFGBVMU JNQMFNFOUBUJPOT UIBU DBO CF PWFSSJEEFO
XIFO OFFEFE 5IJT JT JO DBTF UIFSFƊT B NPSF FƸDJFOU XBZ UP
EP TPNFUIJOH UIBUƊT TQFDJƶD UP ZPVS EBUBUZQF
*G ZPV RVFSZ UIF JOGP BCPVU UIF UZQFDMBTT JO ()$J UIF ƶSTU
MJOF PG UIF EFƶOJUJPO JODMVEFT UIF LJOE TJHOBUVSF GPS ԣ
$)"15&3  '0-%"#-& 

class Foldable (t :: * -> *) where

5IBU ԣ TIPVME CF B IJHIFSLJOEFE UZQF JT OPU TVSQSJTJOH MJTUT


BSF IJHIFSLJOEFE UZQFT 8F OFFE ԣ UP CF B UZQF DPOTUSVDUPS
GPS UIF TBNF SFBTPOT XF EJE XJUI 'VODUPS BOE XF XJMM TFF UIBU
UIF FƵFDUT BSF WFSZ TJNJMBS 5ZQFT UIBU UBLF NPSF UIBO POF
UZQF BSHVNFOU TVDI BT UVQMFT BOE &JUIFS XJMM OFDFTTBSJMZ IBWF
UIFJS ƶSTU UZQF BSHVNFOU JODMVEFE BT QBSU PG UIFJS TUSVDUVSF
1MFBTF OPUF UIBU ZPV XJMM OFFE UP VTF ()$  PS MBUFS
WFSTJPOT GPS BMM UIF FYBNQMFT JO UIJT DIBQUFS UP XPSL "MTP
XIJMF UIF 1SFMVEF BT PG ()$J  JODMVEFT NBOZ DIBOHFT
SFMBUFE UP UIF 'PMEBCMF UZQFDMBTT OPU BMM PG 'PMEBCMF JT JO UIF
1SFMVEF 5P GPMMPX BMPOH XJUI UIF FYBNQMFT JO UIF DIBQUFS
ZPV XJMM OFFE UP JNQPSU %BUB'PMEBCMF BOE %BUB.POPJE GPS
TPNF PG UIF .POPJE OFXUZQFT


 3FWFOHF PG UIF NPOPJET


0OF UIJOH XF EJE OPU UBML BCPVU XIFO XF DPWFSFE GPMET QSF
WJPVTMZ JT UIF JNQPSUBODF PG NPOPJET 'PMEJOH OFDFTTBSJMZ
JNQMJFT B CJOBSZ BTTPDJBUJWF PQFSBUJPO UIBU IBT BO JEFOUJUZ
WBMVF 5IF ƶSTU UXP PQFSBUJPOT EFƶOFE JO 'PMEBCMF NBLF UIJT
FYQMJDJU
$)"15&3  '0-%"#-& 

class Foldable (t :: * -> *) where


fold :: Data.Monoid.Monoid m => t m -> m
foldMap :: Data.Monoid.Monoid m => (a -> m) -> t a -> m

8IJMF fold BMMPXT ZPV UP DPNCJOF FMFNFOUT JOTJEF B 'PME


BCMF TUSVDUVSF VTJOH UIF .POPJE EFƶOFE GPS UIPTF FMFNFOUT
foldMap ƶSTU NBQT FBDI FMFNFOU PG UIF TUSVDUVSF UP B .POPJE
BOE UIFO DPNCJOFT UIF SFTVMUT VTJOH UIBU JOTUBODF PG .POPJE
5IFTF NJHIU TFFN B MJUUMF XFJSE VOUJM ZPV SFBMJ[F UIBU 'PME
BCMF JT SFRVJSJOH UIBU ZPV NBLF UIF JNQMJDJU .POPJE WJTJCMF
JO GPMEJOH PQFSBUJPOT -FUƊT UBLF B MPPL BU B WFSZ CBTJD foldr
PQFSBUJPO BOE TFF IPX JU DPNQBSFT UP fold BOE foldMap

Prelude> foldr (+) 0 [1..5]


15

5IF CJOBSZ BTTPDJBUJWF PQFSBUJPO GPS UIBU GPME JT (


TP XFƊWF
TQFDJƶFE JU XJUIPVU UIJOLJOH PG JU BT B NPOPJE 5IF GBDU UIBU
UIF OVNCFST JO PVS MJTU IBWF PUIFS QPTTJCMF NPOPJET JT OPU
SFMFWBOU PODF XFƊWF TQFDJƶFE XIJDI PQFSBUJPO UP VTF
8F DBO BMSFBEZ TFF GSPN UIF UZQF PG fold UIBU JUƊT OPU HPJOH
UP XPSL UIF TBNF BT foldr CFDBVTF JU EPFTOƊU UBLF B GVODUJPO
GPS JUT ƶSTU BSHVNFOU #VU XF BMTP DBOƊU KVTU GPME VQ B MJTU PG
OVNCFST CFDBVTF UIF fold GVODUJPO EPFTOƊU IBWF B .POPJE
TQFDJƶFE

Prelude> fold (+) [1, 2, 3, 4, 5]


$)"15&3  '0-%"#-& 

-- error message resulting from incorrect


-- number of arguments

Prelude> fold [1, 2, 3, 4, 5]


-- error message resulting from not having
-- an instance of Monoid

4P XIBU XF OFFE UP EP UP NBLF fold XPSL JT TQFDJGZ B


.POPJE JOTUBODF

Prelude> fold [Sum 1, Sum 2, Sum 3, Sum 4, Sum 5]


Sum {getSum = 15}

-- or, less tediously:

Prelude> fold [1, 2, 3, 4, 5 :: Sum Integer]


Sum {getSum = 15}

Prelude> fold [1, 2, 3, 4, 5 :: Product Integer]


Product {getProduct = 120}

*O TPNF DBTFT UIF DPNQJMFS DBO JEFOUJGZ BOE VTF UIF TUBO
EBSE .POPJE GPS B UZQF XJUIPVU VT CFJOH FYQMJDJU

Prelude> foldr (++) "" ["hello", " julie"]


"hello julie"
Prelude> fold ["hello", " julie"]
$)"15&3  '0-%"#-& 

"hello julie"

5IF EFGBVMU .POPJE JOTUBODF GPS MJTUT HJWFT VT XIBU XF OFFE


XJUIPVU IBWJOH UP TQFDJGZ JU

"OE OPX GPS TPNFUIJOH EJƵFSFOU


-FUƊT UVSO PVS BUUFOUJPO OPX UP foldMap 6OMJLF fold foldMap IBT
B GVODUJPO BT JUT ƶSTU BSHVNFOU 6OMJLF foldr UIF ƶSTU GVODUJPO

BSHVNFOU PG foldMap NVTU FYQMJDJUMZ NBQ FBDI FMFNFOU PG UIF


TUSVDUVSF UP B .POPJE

Prelude> foldMap Sum [1, 2, 3, 4]


Sum {getSum = 10}
Prelude> foldMap Product [1, 2, 3, 4]
Product {getProduct = 24}

Prelude> foldMap All [True, False, True]


All {getAll = False}
Prelude> foldMap Any [(3 == 4), (9 > 5)]
Any {getAny = True}

Prelude> foldMap First [Just 1, Nothing, Just 5]


First {getFirst = Just 1}
Prelude> foldMap Last [Just 1, Nothing, Just 5]
Last {getLast = Just 5}
$)"15&3  '0-%"#-& 

*O UIF BCPWF FYBNQMFT UIF GVODUJPO CFJOH BQQMJFE JT B EBUB


DPOTUSVDUPS 5IF EBUB DPOTUSVDUPS JEFOUJƶFT UIF NPOPJE JO
TUBODF ƈ UIF mappend ƈ GPS UIPTF UZQFT *U BMSFBEZ DPOUBJOT
FOPVHI JOGPSNBUJPO UP BMMPX foldMap UP SFEVDF UIF DPMMFDUJPO
PG WBMVFT UP POF TVNNBSZ WBMVF
)PXFWFS foldMap DBO BMTP IBWF B GVODUJPO UP NBQ UIBU JT
EJƵFSFOU GSPN UIF .POPJE JUƊT VTJOH

Prelude> foldMap (*5) [1, 2, 3 :: Product Integer]


Product {getProduct = 750}
-- 5 * 10 * 15
750

Prelude> foldMap (*5) [1, 2, 3 :: Sum Integer]


Sum {getSum = 30}
-- 5 + 10 + 15
30

*U DBO NBQ UIF GVODUJPO UP FBDI WBMVF ƶSTU BOE UIFO VTF UIF
NPOPJE JOTUBODF UP SFEVDF UIFN UP POF WBMVF $PNQBSF UIJT
UP foldr JO XIJDI UIF GVODUJPO IBT UIF NPOPJE JOTUBODF CBLFE
JO

Prelude> foldr (*) 5 [1, 2, 3]


-- (1 * (2 * (3 * 5)))
30
$)"15&3  '0-%"#-& 

*O GBDU EVF UP UIF XBZ foldr XPSLT EFDMBSJOH B .POPJE


JOTUBODF UIBU JT EJƵFSFOU GSPN XIBU JT JNQMJFE JO UIF GPMEJOH
GVODUJPO EPFTOƊU DIBOHF UIF ƶOBM SFTVMU

Prelude> foldr (*) 3 [1, 2, 3 :: Sum Integer]


Sum {getSum = 18}
Prelude> foldr (*) 3 [1, 2, 3 :: Product Integer]
Product {getProduct = 18}

)PXFWFS JU JT XPSUI QPJOUJOH PVU UIBU JG XIBU ZPVƊSF USZJOH


UP GPME POMZ DPOUBJOT POF WBMVF EFDMBSJOH B .POPJE JOTUBODF
XPOƊU DIBOHF UIF CFIBWJPS PG foldMap FJUIFS

Prelude> foldMap (*5) (Just 100) :: Product Integer


Product {getProduct = 500}

Prelude> foldMap (*5) (Just 5) :: Sum Integer


Sum {getSum = 25}

8JUI POMZ POF WBMVF JU EPFTOƊU OFFE UIF .POPJE JOTUBODF


4QFDJGZJOH UIF .POPJE JOTUBODF JT OFDFTTBSZ UP TBUJTGZ UIF UZQF
DIFDLFS CVU XJUI POMZ POF WBMVF UIFSF JT OPUIJOH UP NBQQFOE
*U KVTU BQQMJFT UIF GVODUJPO *U XJMM VTF UIF mempty WBMVF GSPN
UIF EFDMBSFE .POPJE JOTUBODF UIPVHI JO DBTFT XIFSF XIBU
ZPV BSF USZJOH UP GPME JT FNQUZ

Prelude> foldMap (*5) Nothing :: Sum Integer


$)"15&3  '0-%"#-& 

Sum {getSum = 0}
Prelude> foldMap (*5) Nothing :: Product Integer
Product {getProduct = 1}

4P XIBU XFƊWF TFFO TP GBS JT UIBU 'PMEBCMF JT B XBZ PG HFO


FSBMJ[JOH DBUBNPSQIJTNT ƈ GPMEJOH ƈ UP EJƵFSFOU EBUBUZQFT
BOE BU MFBTU JO TPNF DBTFT JU GPSDFT ZPV UP UIJOL BCPVU UIF
NPOPJE ZPVƊSF VTJOH UP DPNCJOF WBMVFT

 %FNPOTUSBUJOH 'PMEBCMF JOTUBODFT


"T XF TBJE BCPWF B NJOJNBM 'PMEBCMF JOTUBODF NVTU IBWF FJUIFS
foldr PS foldMap "OZ PG UIF PUIFS GVODUJPOT JO UIJT UZQFDMBTT
DBO CF EFSJWFE GSPN POF PS UIF PUIFS PG UIPTF 8JUI UIBU TBJE
MFUƊT UVSO PVS BUUFOUJPO UP JNQMFNFOUJOH 'PMEBCMF JOTUBODFT
GPS EJƵFSFOU UZQFT

*EFOUJUZ
8FƊMM LJDL UIJOHT PƵ CZ XSJUJOH B 'PMEBCMF JOTUBODF GPS *EFOUJUZ

data Identity a =
Identity a

8FƊSF POMZ PCMJHBUFE UP XSJUF foldr PS foldMap CVU XFƊMM XSJUF


CPUI QMVT GPMEM KVTU TP ZPV IBWF UIF HJTU PG JU
$)"15&3  '0-%"#-& 

instance Foldable Identity where


foldr f z (Identity x) = f x z

foldl f z (Identity x) = f z x

foldMap f (Identity x) = f x

8JUI foldr BOE foldl XFƊSF EPJOH CBTJDBMMZ UIF TBNF UIJOH
CVU XJUI UIF BSHVNFOUT TXBQQFE 8F EJEOƊU OFFE UP EP BOZ
UIJOH TQFDJBM GPS foldMap
*U NBZ TFFN TUSBOHF UP UIJOL PG GPMEJOH POF WBMVF 8IFO
XFƊWF UBMLFE BCPVU DBUBNPSQIJTNT QSFWJPVTMZ XFƊWF GPDVTFE
PO IPX UIFZ DBO SFEVDF B CVODI PG WBMVFT EPXO UP POF TVN
NBSZ WBMVF *O UIF DBTF PG UIJT *EFOUJUZ DBUBNPSQIJTN UIPVHI
UIF QPJOU JT MFTT UP SFEVDF UIF WBMVFT JOTJEF UIF TUSVDUVSF UP
POF WBMVF BOE NPSF UP DPOTVNF PS VTF UIF WBMVF

Main> foldr (*) 1 (Identity 5)


5
Main> foldl (*) 5 (Identity 5)
25

Main> foldMap (*5) (Identity 100) :: Product Integer


Product {getProduct = 500}
$)"15&3  '0-%"#-& 

.BZCF
5IJT POF JT B MJUUMF NPSF JOUFSFTUJOH CFDBVTF VOMJLF XJUI *EFO
UJUZ XF IBWF UP BDDPVOU GPS UIF /PUIJOH DBTFT 8IFO UIF
.BZCF WBMVF UIBU XFƊSF GPMEJOH JT /PUIJOH XF OFFE UP CF BCMF
UP SFUVSO TPNF ƌ[FSPƍ WBMVF XIJMF EPJOH OPUIJOH XJUI UIF
GPMEJOH GVODUJPO CVU BMTP EJTQPTJOH PG UIF .BZCF TUSVDUVSF
'PS foldr BOE foldl UIBU [FSP WBMVF JT UIF TUBSU WBMVF QSPWJEFE

Prelude> foldr (+) 1 Nothing


1

0O UIF PUIFS IBOE GPS foldMap XF VTF UIF .POPJEƊT JEFOUJUZ


WBMVF BT PVS [FSP

Prelude> foldMap (+1) Nothing :: Sum Integer


Sum {getSum = 0}

8IFO UIF WBMVF JT B +VTU WBMVF UIPVHI XF OFFE UP BQQMZ


UIF GPMEJOH GVODUJPO UP UIF WBMVF BOE BHBJO EJTQPTF PG UIF
TUSVDUVSF

Prelude> foldr (+) 1 (Just 3)


4
Prelude> foldMap (+1) $ Just 3 :: Sum Integer
Sum {getSum = 4}
$)"15&3  '0-%"#-& 

4P MFUƊT MPPL BU UIF JOTUBODF 8FƊMM VTF B GBLF .BZCF UZQF


BHBJO UP BWPJE DPOƷJDU XJUI UIF .BZCF JOTUBODF UIBU BMSFBEZ
FYJTUT

instance Foldable Optional where


foldr _ z Nada = z
foldr f z (Yep x) = f x z

foldl _ z Nada = z
foldl f z (Yep x) = f z x

foldMap _ Nada = mempty


foldMap f (Yep a) = f a

/PUF UIBU JG ZPV EPOƊU UFMM JU XIBU .POPJE ZPV NFBO JUƊMM
XIJOHF BCPVU UIF UZQF CFJOH BNCJHVPVT

Prelude> foldMap (+1) Nada

No instance for (Num a0) arising from a use of ‘it’


The type variable ‘a0’ is ambiguous
(... blah blah who cares ...)

4P XF OFFE UP BTTFSU B UZQF UIBU IBT B .POPJE GPS UIJT UP


XPSL

Prelude> import Data.Monoid


$)"15&3  '0-%"#-& 

Prelude> foldMap (+1) Nada :: Sum Int


Sum {getSum = 0}
Prelude> foldMap (+1) Nada :: Product Int
Product {getProduct = 1}

Prelude> foldMap (+1) (Just 1) :: Sum Int


Sum {getSum = 2}

8JUI B /BEB WBMVF BOE B EFDMBSFE UZQF PG 4VN *OU HJWJOH


VT PVS .POPJE
GPME.BQ HBWF VT Sum 0 CFDBVTF UIBU XBT UIF
NFNQUZ PS JEFOUJUZ GPS 4VN 4JNJMBSMZ XJUI /BEB BOE 1SPEVDU
XF HPU Product 1 CFDBVTF UIBU XBT UIF JEFOUJUZ GPS 1SPEVDU

 4PNF CBTJD EFSJWFE PQFSBUJPOT


5IF 'PMEBCMF UZQFDMBTT JODMVEFT TPNF PUIFS PQFSBUJPOT UIBU
XF IBWFOƊU DPWFSFE JO UIJT DPOUFYU ZFU 4PNF PG UIFTF TVDI
BT length XFSF QSFWJPVTMZ EFƶOFE GPS VTF XJUI MJTUT CVU UIFJS
UZQFT IBWF CFFO HFOFSBMJ[FE OPX UP NBLF UIFN VTFGVM XJUI
PUIFS UZQFT PG EBUB TUSVDUVSFT #FMPX BSF EFTDSJQUJPOT UZQF
TJHOBUVSFT BOE FYBNQMFT GPS TFWFSBM PG UIFTF

-- | List of elements of a structure, from left to right.


toList :: t a -> [a]

Prelude> toList (Just 1)


[1]
$)"15&3  '0-%"#-& 

Prelude> map toList [Just 1, Just 2, Just 3]


[[1],[2],[3]]
Prelude> concatMap toList [Just 1, Just 2, Just 3]
[1,2,3]

Prelude> concatMap toList [Just 1, Just 2, Nothing]


[1,2]
Prelude> toList (1, 2)
[2]
-- it doesn't put the 1 in the list for
-- the same reason that fmap doesn't apply
-- a function to the 1

-- | Test whether the structure is empty.


-- The default implementation is
-- optimized for structures that are similar
-- to cons-lists, because there
-- is no general way to do better.
null :: t a -> Bool

/PUJDF UIBU null SFUVSOT 5SVF PO -Fǒ BOE /PUIJOH WBMVFT


KVTU BT JU EPFT PO FNQUZ MJTUT BOE TP GPSUI

Prelude> null (Left 3)


True
Prelude> null []
True
$)"15&3  '0-%"#-& 

Prelude> null Nothing


True
Prelude> null (1, 2)
False
Prelude> fmap null [Just 1, Just 2, Nothing]
[False,False,True]

5IF OFYU POF length SFUVSOT B DPVOU PG IPX NBOZ Ԑ WBMVFT


JOIBCJU UIF t a *O B MJTU UIBU DPVME CF NVMUJQMF Ԑ WBMVFT EVF UP
UIF EFƶOJUJPO PG UIBU EBUBUZQF *UƊT JNQPSUBOU UP OPUF UIPVHI
UIBU GPS UVQMFT UIF ƶSTU BSHVNFOU BT XFMM BT UIF MFǒNPTU PS
PVUFSNPTU UZQF BSHVNFOUT PG EBUBUZQFT TVDI BT .BZCF BOE
&JUIFS
JT QBSU PG UIF ԣ IFSF OPU QBSU PG UIF Ԑ

-- | Returns the size/length of a finite


-- structure as an 'Int'. The default
-- implementation is optimized for structures
-- that are similar to cons-lists, because there
-- is no general way to do better.
length :: t a -> Int

Prelude> length (1, 2)


1
Prelude> length [(1, 2), (3, 4), (5, 6)]
3
Prelude> fmap length [(1, 2), (3, 4), (5, 6)]
$)"15&3  '0-%"#-& 

[1,1,1]

Prelude> fmap length Just [1, 2, 3]


1
-- the a of Just a in this case is a list, and
-- there is only one list

Prelude> fmap length [Just 1, Just 2, Just 3]


[1,1,1]
Prelude> fmap length [Just 1, Just 2, Nothing]
[1,1,0]

-- | Does the element occur in the structure?


elem :: Eq a => a -> t a -> Bool

8FƊWF VTFE &JUIFS JO UIF GPMMPXJOH FYBNQMF TFU UP EFNPO


TUSBUF UIF CFIBWJPS PG 'PMEBCMF GVODUJPOT XJUI -Fǒ WBMVFT "T
XF TBX XJUI 'VODUPS ZPV DBOƊU NBQ PWFS UIF MFǒ EBUB DPOTUSVD
UPS CFDBVTF UIF MFǒ UZQF BSHVNFOU JT QBSU PG UIF TUSVDUVSF *O
UIF GPMMPXJOH FYBNQMF TFU UIBU NFBOT UIBU elem DBOƊU TFF JOTJEF
UIF -Fǒ DPOTUSVDUPS UP XIBUFWFS UIF WBMVF JT TP UIF SFTVMU XJMM
CF 'BMTF FWFO JG UIF WBMVF NBUDIFT

Prelude> elem 2 (Just 3)


False
Prelude> elem True (Left False)
False
$)"15&3  '0-%"#-& 

Prelude> elem True (Left True)


False
Prelude> elem True (Right False)
False
Prelude> elem True (Right True)
True
Prelude> fmap (elem 3) [Right 1, Right 2, Right 3]
[False,False,True]

-- | The largest element of a non-empty structure.


maximum :: Ord a => t a -> a

-- | The least element of a non-empty structure.


minimum :: Ord a => t a -> a

)FSF OPUJDF UIBU -Fǒ BOE /PUIJOH BOE TJNJMBS


WBMVFT BSF
FNQUZ GPS UIF QVSQPTFT PG UIFTF GVODUJPOT

Prelude> maximum [10, 12, 33, 5]


33
Prelude> fmap maximum [Just 2, Just 10, Just 4]
[2,10,4]
Prelude> fmap maximum (Just [3, 7, 10, 2])
Just 10
$)"15&3  '0-%"#-& 

Prelude> minimum "julie"


'e'
Prelude> fmap minimum (Just "julie")
Just 'e'
Prelude> fmap minimum [Just 'j', Just 'u', Just 'l']
"jul"

Prelude> fmap minimum [Just 4, Just 3, Nothing]


[4,3,*** Exception: minimum: empty structure
Prelude> minimum (Left 3)
*** Exception: minimum: empty structure

8FƊWF TFFO sum BOE product CFGPSF BOE UIFZ EP XIBU UIFJS
OBNFT TVHHFTU SFUVSO UIF TVN BOE QSPEVDU PG UIF NFNCFST
PG B TUSVDUVSF

-- | The 'sum' function computes the sum of the


-- numbers of a structure.
sum :: (Foldable t, Num a) => t a -> a

-- | The 'product' function computes the product


-- of the numbers of a structure.
product :: (Foldable t, Num a) => t a -> a

"OE OPX GPS TPNF FYBNQMFT

Prelude> sum (7, 5)


$)"15&3  '0-%"#-& 

5
Prelude> fmap sum [(7, 5), (3, 4)]
[5,4]
Prelude> fmap sum (Just [1, 2, 3, 4, 5])
Just 15
Prelude> product Nothing
1
Prelude> fmap product (Just [])
Just 1
Prelude> fmap product (Right [1, 2, 3])
Right 6

&YFSDJTFT -JCSBSZ 'VODUJPOT


*NQMFNFOU UIF GVODUJPOT JO UFSNT PG foldMap PS foldr GSPN
'PMEBCMF UIFO USZ UIFN PVU XJUI NVMUJQMF UZQFT UIBU IBWF
'PMEBCMF JOTUBODFT

 5IJT BOE UIF OFYU POF BSF OJDFS XJUI foldMap CVU foldr JT
ƶOF UPP

sum :: (Foldable t, Num a) => t a -> a

 product :: (Foldable t, Num a) => t a -> a

 elem :: (Foldable t, Eq a) => a -> t a -> Bool

 minimum :: (Foldable t, Ord a) => t a -> Maybe a


$)"15&3  '0-%"#-& 

 maximum :: (Foldable t, Ord a) => t a -> Maybe a

 null :: (Foldable t) => t a -> Bool

 length :: (Foldable t) => t a -> Int

 4PNF TBZ UIJT JT BMM 'PMEBCMF BNPVOUT UP

toList :: (Foldable t) => t a -> [a]

 )JOU VTF foldMap

-- | Combine the elements of a structure using a monoid.


fold :: (Foldable t, Monoid m) => t m -> m

 %FƶOF GPME.BQ JO UFSNT PG GPMES

foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m

 $IBQUFS &YFSDJTFT


8SJUF 'PMEBCMF JOTUBODFT GPS UIF GPMMPXJOH EBUBUZQFT

 data Constant a b =
Constant a

 data Two a b =
Two a b
$)"15&3  '0-%"#-& 

 data Three a b c =
Three a b c

 data Three' a b =
Three' a b b

 data Four' a b =
Four' a b b b

5IJOLJOH DBQ UJNF 8SJUF B ƶMUFS GVODUJPO GPS 'PMEBCMF UZQFT


VTJOH GPME.BQ

filterF :: (Applicative f, Foldable t, Monoid (f a))


=> (a -> Bool) -> t a -> f a
filterF = undefined

 'PMMPXVQ SFTPVSDFT


 +BLVC "SOPME 'PMEBCMF BOE 5SBWFSTBCMF
$IBQUFS 

5SBWFSTBCMF

0 5IPV IBTU EBNOBCMF


JUFSBUJPO BOE BSU JOEFFE
BCMF UP DPSSVQU B TBJOU

4IBLFTQFBSF


$)"15&3  53"7&34"#-& 

 5SBWFSTBCMF
'VODUPS HJWFT VT B XBZ UP USBOTGPSN BOZ WBMVFT FNCFEEFE
JO TUSVDUVSF "QQMJDBUJWF XF TBX JT B NPOPJEBM GVODUPS BOE
HJWFT VT B XBZ UP USBOTGPSN BOZ WBMVFT DPOUBJOFE XJUIJO B
TUSVDUVSF VTJOH B GVODUJPO UIBU JT BMTP FNCFEEFE JO TUSVDUVSF
5IJT NFBOT UIBU FBDI BQQMJDBUJPO QSPEVDFT UIF FƵFDU PG BEEJOH
TUSVDUVSF XIJDI JT UIFO BQQMJDBUJWFMZ DPNCJOFE 'PMEBCMF HJWFT
VT B XBZ UP QSPDFTT WBMVFT FNCFEEFE JO B TUSVDUVSF BT JG UIFZ FY
JTUFE JO B TFRVFOUJBM PSEFS BT XFƊWF TFFO FWFS TJODF XF MFBSOFE
BCPVU MJTU GPMEJOH
5SBWFSTBCMF XBT JOUSPEVDFE JO UIF TBNF QBQFS BT "QQMJDBUJWF
BOE JUT JOUSPEVDUJPO UP 1SFMVEF EJEOƊU DPNF VOUJM UIF SFMFBTF PG
()$  )PXFWFS JU XBT BWBJMBCMF BT QBSU PG UIF base MJCSBSZ
GPS NVDI MPOHFS UIBO UIBU 5SBWFSTBCMF EFQFOET PO "QQMJDB
UJWF BOE UIVT 'VODUPS BOE JT BMTP TVQFSDMBTTFE CZ 'PMEBCMF
5SBWFSTBCMF BMMPXT ZPV UP USBOTGPSN FMFNFOUT JOTJEF UIF
TUSVDUVSF MJLF B 'VODUPS QSPEVDJOH "QQMJDBUJWF FƵFDUT BMPOH
UIF XBZ BOE MJǒ UIPTF QPUFOUJBMMZ NVMUJQMF JOTUBODFT PG "Q
QMJDBUJWF TUSVDUVSF PVUTJEF PG UIF 5SBWFSTBCMF TUSVDUVSF *U JT
DPNNPOMZ EFTDSJCFE BT B XBZ UP USBWFSTF B EBUB TUSVDUVSF
NBQQJOH B GVODUJPO JOTJEF B TUSVDUVSF XIJMF BDDVNVMBUJOH UIF
BQQMJDBUJWF DPOUFYUT BMPOH UIF XBZ 5IJT JT FBTJFTU UP TFF QFS
IBQT UISPVHI MJCFSBM EFNPOTUSBUJPO PG FYBNQMFT TP MFUƊT HFU
UP JU
*O UIJT DIBQUFS XF XJMM
$)"15&3  53"7&34"#-& 

Ƒ FYQMBJO UIF 5SBWFSTBCMF UZQFDMBTT BOE JUT DBOPOJDBM GVOD


UJPOT

Ƒ FYQMPSF FYBNQMFT PG 5SBWFSTBCMF JO QSBDUJDBM VTF

Ƒ UJEZ VQ TPNF DPEF VTJOH UIJT UZQFDMBTT

Ƒ BOE PG DPVSTF XSJUF TPNF 5SBWFSTBCMF JOTUBODFT

 5IF 5SBWFSTBCMF UZQFDMBTT


EFƶOJUJPO
5IJT JT UIF UZQFDMBTT EFƶOJUJPO BT JU BQQFBST JO UIF MJCSBSZ PO
)BDLBHF %BUB5SBWFSTBCMF


class (Functor t, Foldable t) => Traversable t where


{-# MINIMAL traverse | sequenceA #-}

-- | Map each element of a structure to an action,


-- evaluate these actions from left to right, and
-- collect the results. For a version that ignores
-- the results see 'Data.Foldable.traverse_'.
$)"15&3  53"7&34"#-& 

traverse :: Applicative f =>


(a -> f b)
-> t a
-> f (t b)
traverse f = sequenceA . fmap f

-- | Evaluate each action in the structure from


-- left to right, and collect the results.
-- For a version that ignores the results see
-- 'Data.Foldable.sequenceA_'.
sequenceA :: Applicative f => t (f a) -> f (t a)
sequenceA = traverse id

" NJOJNBM JOTUBODF GPS UIJT UZQFDMBTT QSPWJEFT BO JNQMF


NFOUBUJPO PG FJUIFS traverse PS sequenceA CFDBVTF BT ZPV DBO
TFF UIFZ DBO CF EFƶOFE JO UFSNT PG FBDI PUIFS "T XJUI 'PME
BCMF XF DBO EFƶOF NPSF UIBO UIF CBSF NJOJNVN JG XF DBO
MFWFSBHF JOGPSNBUJPO TQFDJƶD UP PVS EBUBUZQF UP NBLF UIF CF
IBWJPS NPSF FƸDJFOU 8FƊSF HPJOH UP GPDVT PO UIFTF UXP GVOD
UJPOT JO UIJT DIBQUFS UIPVHI BT UIPTF BSF UIF NPTU UZQJDBMMZ
VTFGVM

 TFRVFODF"
8F XJMM TUBSU XJUI TPNF FYBNQMFT PG sequenceA JO BDUJPO BT JU JT
UIF TJNQMFS PG UIF UXP :PV DBO TFF GSPN UIF UZQF TJHOBUVSF
$)"15&3  53"7&34"#-& 

BCPWF UIBU UIF FƵFDU PG sequenceA JT ƷJQQJOH UXP DPOUFYUT PS


TUSVDUVSFT *U EPFTOƊU CZ JUTFMG BMMPX ZPV UP BQQMZ BOZ GVODUJPO
UP UIF Ԑ WBMVF JOTJEF UIF TUSVDUVSF JU POMZ ƷJQT UIF MBZFST PG
TUSVDUVSF BSPVOE $PNQBSF UIFTF

Prelude> sum [1, 2, 3]


6
Prelude> fmap sum [Just 1, Just 2, Just 3]
[1,2,3]
Prelude> (fmap . fmap) sum Just [1, 2, 3]
Just 6
Prelude> fmap product [Just 1, Just 2, Nothing]
[1,2,1]

5P UIFTF

Prelude> fmap Just [1, 2, 3]


[Just 1,Just 2,Just 3]
Prelude> sequenceA $ fmap Just [1, 2, 3]
Just [1,2,3]
Prelude> sequenceA [Just 1, Just 2, Just 3]
Just [1,2,3]
Prelude> sequenceA [Just 1, Just 2, Nothing]
Nothing
Prelude> fmap sum $ sequenceA [Just 1, Just 2, Just 3]
Just 6
Prelude> let xs = [Just 3, Just 4, Nothing]
$)"15&3  53"7&34"#-& 

Prelude> fmap product (sequenceA xs)


Nothing

*O UIF ƶSTU FYBNQMF VTJOH sequenceA KVTU ƷJQT UIF TUSVDUVSFT


BSPVOE ƈ JOTUFBE PG B MJTU PG .BZCF WBMVFT ZPV HFU B .BZCF
PG B MJTU WBMVF *O UIF OFYU UXP FYBNQMFT XF DBO MJǒ B GVODUJPO
PWFS UIF .BZCF TUSVDUVSF BOE BQQMZ JU UP UIF MJTU UIBU JT JOTJEF
JG XF IBWF B Just a WBMVF BǒFS BQQMZJOH UIF sequenceA
*UƊT XPSUI NFOUJPOJOH IFSF UIBU UIF %BUB.BZCF MJCSBSZ IBT B
GVODUJPO DBMMFE catMaybes UIBU PƵFST B EJƵFSFOU XBZ PG IBOEMJOH
B MJTU PG .BZCF WBMVFT

Prelude> import Data.Maybe


Prelude> catMaybes [Just 1, Just 2, Just 3]
[1,2,3]
Prelude> catMaybes [Just 1, Just 2, Nothing]
[1,2]
Prelude> let xs = [Just 1, Just 2, Just 3, Nothing]
Prelude> sum $ catMaybes xs
6
Prelude> fmap sum $ sequenceA xs
Nothing

6TJOH catMaybes BMMPXT ZPV UP TVN PS PUIFSXJTF QSPDFTT

UIF MJTU PG .BZCF WBMVFT FWFO JG UIFSFƊT QPUFOUJBMMZ B /PUIJOH


WBMVF MVSLJOH XJUIJO
$)"15&3  53"7&34"#-& 

 USBWFSTF
-FUƊT MPPL OFYU BU UIF UZQF PG traverse

traverse
:: (Applicative f, Traversable t) =>
(a -> f b) -> t a -> f (t b)

:PV NJHIU OPUJDF B TJNJMBSJUZ CFUXFFO UIBU BOE UIF UZQFT PG


fmap BOE (=<<) ƷJQ CJOE


fmap :: (a -> b) -> f a -> f b


(=<<) :: (a -> m b) -> m a -> m b
traverse :: (a -> f b) -> t a -> f (t b)

8FƊSF TUJMM NBQQJOH B GVODUJPO PWFS TPNF FNCFEEFE WBMVF T



MJLF fmap CVU TJNJMBS UP flip bind UIBU GVODUJPO JT JUTFMG HFOFSBU
JOH NPSF TUSVDUVSF )PXFWFS VOMJLF flip bind UIBU TUSVDUVSF
DBO CF PG B EJƵFSFOU UZQF UIBO UIF TUSVDUVSF XF MJǒFE PWFS UP BQ
QMZ UIF GVODUJPO "OE BU UIF FOE JU XJMM ƷJQ UIF UXP TUSVDUVSFT
BSPVOE BT sequenceA EJE
*O GBDU BT XF TBX JO UIF UZQFDMBTT EFƶOJUJPO traverse JT fmap
DPNQPTFE XJUI sequenceA

traverse f = sequenceA . fmap f

-FUƊT MPPL BU IPX UIBU XPSLT JO QSBDUJDF


$)"15&3  53"7&34"#-& 

Prelude> fmap Just [1, 2, 3]


[Just 1,Just 2,Just 3]
Prelude> sequenceA $ fmap Just [1, 2, 3]
Just [1,2,3]
Prelude> sequenceA . fmap Just $ [1, 2, 3]
Just [1,2,3]
Prelude> traverse Just [1, 2, 3]
Just [1,2,3]

8FƊMM SVO UISPVHI TPNF MPOHFS FYBNQMFT JO B NPNFOU CVU


UIF HFOFSBM JEFB JT UIBU BOZUJNF ZPVƊSF VTJOH sequenceA . fmap
f ZPV DBO VTF traverse UP BDIJFWF UIF TBNF SFTVMU JO POF TUFQ

NBQ. JT KVTU USBWFSTF


:PV NBZ IBWF TFFO B TMJHIUMZ EJƵFSFOU XBZ PG FYQSFTTJOH USB
WFSTF CFGPSF JO UIF GPSN PG mapM
*O WFSTJPOT PG ()$ QSJPS UP  UIF UZQF PG mapM XBT UIF
GPMMPXJOH

mapM :: Monad m => (a -> m b) -> [a] -> m [b]

-- contrast with

traverse :: Applicative f =>


(a -> f b) -> t a -> f (t b)
$)"15&3  53"7&34"#-& 

8F DBO UIJOL PG traverse JO 5SBWFSTBCMF BT BCTUSBDUJOH UIF []


JO mapM UP CFJOH BOZ 5SBWFSTBCMF EBUB TUSVDUVSF BOE HFOFSBMJ[JOH
UIF .POBE SFRVJSFNFOU UP POMZ OFFE BO "QQMJDBUJWF 5IJT JT
WBMVBCMF BT JU NFBOT XF DBO VTF UIJT QBUUFSO NPSF XJEFMZ BOE
XJUI NPSF DPEF 'PS FYBNQMF UIF MJTU EBUBUZQF JT ƶOF GPS
TNBMM QMVSBMJUJFT PG WBMVFT CVU JO NPSF QFSGPSNBODFTFOTJUJWF
DPEF ZPV NBZ XBOU UP VTF B 7FDUPS GSPN UIF WFDUPS MJCSBSZ
8JUI traverse ZPV XPOƊU IBWF UP DIBOHF ZPVS DPEF CFDBVTF
UIF QSJNBSZ 7FDUPS EBUBUZQF IBT B 5SBWFSTBCMF JOTUBODF BOE
TP TIPVME XPSL ƶOF
4JNJMBSMZ UIF UZQF GPS sequence JO ()$ WFSTJPOT QSJPS UP
 JT KVTU B MFTT VTFGVM sequenceA

sequence :: Monad m =>


[m a]
-> m [a]

-- contrast with

sequenceA :: (Applicative f, Traversable t) =>


t (f a)
-> f (t a)

"HBJO XFƊSF HFOFSBMJ[JOH UIF MJTU UP BOZ 5SBWFSTBCMF BOE


XFBLFOJOH UIF .POBE SFRVJSFNFOU UP KVTU "QQMJDBUJWF

http://hackage.haskell.org/package/vector
$)"15&3  53"7&34"#-& 

 4P XIBUƊT USBWFSTBCMF GPS


*O B MJUFSBM TFOTF BOZUJNF ZPV OFFE UP ƷJQ UXP UZQF DPOTUSVD
UPST BSPVOE PS NBQ TPNFUIJOH BOE UIFO ƷJQ UIFN BSPVOE
UIBUƊT QSPCBCMZ 5SBWFSTBCMF

sequenceA :: Applicative f => t (f a) -> f (t a)

traverse :: Applicative f =>


(a -> f b) -> t a -> f (t b)

8FƊMM LJDL BSPVOE TPNF IZQPUIFUJDBM GVODUJPOT BOE WBMVFT


XJUIPVU CPUIFSJOH UP JNQMFNFOU UIFN JO UIF 3&1- UP TFF XIFO
XF NBZ XBOU traverse PS sequenceA

Prelude> let f = undefined :: a -> Maybe b


Prelude> let xs = undefined :: [a]
Prelude> :t map f xs
map f xs :: [Maybe b]

#VU XIBU JG XF XBOU B WBMVF PG UZQF Maybe [b] 5IF GPMMPXJOH


XJMM XPSL CVU XF DBO EP CFUUFS

Prelude> :t sequenceA $ map f xs


sequenceA $ map f xs :: Maybe [a]

*UƊT VTVBMMZ CFUUFS UP VTF traverse XIFOFWFS XF TFF B sequence


PS sequenceA DPNCJOFE XJUI B map PS fmap
$)"15&3  53"7&34"#-& 

Prelude> :t traverse f xs
traverse f xs :: Maybe [b]

/FYU XFƊMM TUBSU MPPLJOH BU SFBM FYBNQMFT PG XIFO ZPVƊE XBOU


UP EP UIJT

 .PSTF DPEF SFWJTJUFE


8FƊSF HPJOH UP DBMM CBDL UP XIBU XF EJE JO UIF 5FTUJOH DIBQUFS
XJUI UIF .PSTF DPEF FYBNQMF UP MPPL BU B OJDF FYBNQMF PG IPX
UP VTF traverse -FUƊT SFDBMM XIBU XF IBE EPOF UIFSF

stringToMorse :: String -> Maybe [Morse]


stringToMorse s = sequence $ fmap charToMorse s

-- what we want to do:


stringToMorse :: String -> Maybe [Morse]
stringToMorse = traverse charToMorse

/PSNBMMZ ZPV NJHIU FYQFDU UIBU JG ZPV NBQQFE BO (a ->


f b) PWFS B t a ZPVƊE FOE VQ XJUI t (f b) CVU traverse ƷJQT
UIBU BSPVOE 3FNFNCFS XF IBE FBDI DIBSBDUFS DPOWFSTJPO
XSBQQFE JO B Maybe EVF UP UIF QPTTJCJMJUZ PG HFUUJOH DIBSBDUFST JO
B TUSJOH UIBU BSFOƊU USBOTMBUBCMF JOUP .PSTF PS JO UIF PQQPTJUF
DPOWFSTJPO BSFOƊU .PSTF DIBSBDUFST


Prelude> morseToChar "gobbledegook"


$)"15&3  53"7&34"#-& 

Nothing
Prelude> morseToChar "-.-."
Just 'c'

8F DBO VTF fromMaybe UP SFNPWF UIF Maybe MBZFS

Prelude> import Data.Maybe


Prelude Data.Maybe> fromMaybe ' ' (morseToChar "-.-.")
'c'

Prelude> stringToMorse "chris"


Just ["-.-.","....",".-.","..","..."]

Prelude> import Data.Maybe


Prelude> fromMaybe [] (stringToMorse "chris")
["-.-.","....",".-.","..","..."]

8FƊMM EFƶOF B MJUUMF IFMQFS GPS VTF JO UIF GPMMPXJOH FYBNQMFT

Prelude> let morse s = fromMaybe [] (stringToMorse s)


Prelude> :t morse
morse :: String -> [Morse]

/PX JG XF fmap morseToChar XF HFU B MJTU PG Maybe WBMVFT

Prelude> fmap morseToChar (morse "chris")


[Just 'c',Just 'h',Just 'r',Just 'i',Just 's']
$)"15&3  53"7&34"#-& 

8F EPOƊU XBOU catMaybes IFSF CFDBVTF JU ESPQT UIF /PUIJOH


WBMVFT 8IBU XF XBOU IFSF JT GPS BOZ /PUIJOH WBMVFT UP NBLF
UIF ƶOBM SFTVMU /PUIJOH 5IF GVODUJPO UIBU HJWFT VT XIBU XF
XBOU GPS UIJT JT sequence 8F EJE VTF sequence JO UIF PSJHJOBM
WFSTJPO PG UIF stringToMorse GVODUJPO sequence JT VTFGVM GPS
ƷJQQJOH ZPVS UZQFT BSPVOE BT XFMM OPUF UIF QPTJUJPOT PG UIF
ԣ BOE Ԝ
 5IFSF JT B sequence JO 1SFMVEF BOE BOPUIFS NPSF
HFOFSJD WFSTJPO JO Data.Traversable

Prelude> :t sequence
sequence :: Monad m => [m a] -> m [a]

-- more general, can be used with types


-- other than List
Prelude> import Data.Traversable as T
Prelude T> :t T.sequence
T.sequence :: (Traversable t, Monad m)
=> t (m a) -> m (t a)

5P VTF UIJT PWFS B MJTU PG Maybe PS PUIFS NPOBEJD


WBMVFT XF
OFFE UP DPNQPTF JU XJUI fmap

Prelude> :t (sequence .) . fmap


(sequence .) . fmap
:: (Monad m, Traversable t) =>
(a1 -> m a) -> t a1 -> m (t a)
$)"15&3  53"7&34"#-& 

Prelude> sequence $ fmap morseToChar (morse "chris")


Just "chris"

Prelude> sequence $ fmap morseToChar (morse "julie")


Just "julie"

5IF XFJSE MPPLJOH DPNQPTJUJPO XIJDI ZPVƊWF QPTTJCMZ BMTP


TFFO JO UIF GPSN PG (join .) . fmap JT CFDBVTF fmap UBLFT UXP
OPU POF
BSHVNFOUT TP UIF FYQSFTTJPOT BSFOƊU QSPQFS VOMFTT
XF DPNQPTF UXJDF UP BXBJU B TFDPOE BSHVNFOU GPS fmap UP HFU
BQQMJFE UP

-- we want this
(sequence .) . fmap = \ f xs -> sequence (fmap f xs)

-- not this
sequence . fmap = \ f -> sequence (fmap f)

5IJT DPNQPTJUJPO PG sequence BOE fmap JT TP DPNNPO UIBU


traverse JT OPX B TUBOEBSE 1SFMVEF GVODUJPO $PNQBSF UIF
BCPWF UP UIF GPMMPXJOH

*Morse T> traverse morseToChar (morse "chris")


Just "chris"

*Morse T> traverse morseToChar (morse "julie")


Just "julie"
$)"15&3  53"7&34"#-& 

4P traverse JT KVTU fmap BOE UIF 5SBWFSTBCMF WFSTJPO PG sequence


CPMUFE UPHFUIFS JOUP POF DPOWFOJFOU GVODUJPO sequence JT UIF
VOJRVF CJU CVU ZPV OFFE UP EP UIF fmap ƶSTU NPTU PG UIF UJNF
TP ZPV FOE VQ VTJOH traverse 5IJT JT WFSZ TJNJMBS UP UIF XBZ
>>= JT KVTU join DPNQPTFE XJUI fmap XIFSF join JT UIF CJU UIBU JT
VOJRVF UP Monad

 "YJOH UFEJPVT DPEF


5SZ UP CFBS XJUI VT GPS B NPNFOU BOE SFBMJ[F UIBU UIF GPMMPXJOH
JT SFBM CVU BMTP JOUFOUJPOBMMZ GBLF DPEF 5IBU JT POF PG UIF
BVUIPST IFMQFE TPNFCPEZ XJUI SFGBDUPSJOH UIFJS DPEF BOE
UIJT TJNQMJƶFE WFSTJPO JT XIBU ZPVS BVUIPS XBT HJWFO 0OF PG
UIF TUSFOHUIT PG )BTLFMM JT UIBU XF DBO XPSL JO UFSNT PG UZQFT
XJUIPVU XPSSZ BCPVU DPEF UIBU BDUVBMMZ SVOT TPNFUJNFT 5IJT
DPEF JT GSPN "MFY 1FUSPW XIP XBT LJDLJOH TPNFUIJOH BSPVOE
PO 5XJUUFS

-- Thanks for the great example Alex :)


data Query = Query
data SomeObj = SomeObj
data IoOnlyObj = IoOnlyObj
data Err = Err
$)"15&3  53"7&34"#-& 

-- There's a decoder function that makes


-- some object from String
decodeFn :: String -> Either Err SomeObj
decodeFn = undefined

-- There's a query, that runs against DB and


-- returns array of strings
fetchFn :: Query -> IO [String]
fetchFn = undefined

-- there's some additional "context initializer",


-- that also has IO side-effects
makeIoOnlyObj :: [SomeObj]
-> IO [(SomeObj, IoOnlyObj)]
makeIoOnlyObj = undefined

-- before
pipelineFn :: Query
-> IO (Either Err [(SomeObj, IoOnlyObj)])
pipelineFn query = do
a <- fetchFn query
case sequence (map decodeFn a) of
(Left err) -> return $ Left $ err
(Right res) -> do
a <- makeIoOnlyObj res
return $ Right a
$)"15&3  53"7&34"#-& 

5IF PCKFDUJWF XBT UP DMFBO VQ UIJT DPEF " GFX UIJOHT NBEF
UIFN TVTQJDJPVT

 5IF VTF PG sequence BOE map

 .BOVBMMZ DBTJOH PO UIF SFTVMU PG UIF sequence BOE UIF map

 #JOEJOH NPOBEJDBMMZ PWFS UIF &JUIFS POMZ UP QFSGPSN


BOPUIFS NPOBEJD *0
BDUJPO JOTJEF PG UIBU

)FSFƊT XIBU UIF QJQFMJOF GVODUJPO HPU QBSFE EPXO UP

pipelineFn :: Query
-> IO (Either Err [(SomeObj, IoOnlyObj)])
pipelineFn query = do
a <- fetchFn query
traverse makeIoOnlyObj (mapM decodeFn a)

5IBOLT UP NFSJKO PO UIF *3$ DIBOOFM GPS IFMQJOH XJUI UIJT


FYBNQMF 8F DBO NBLF JU QPJOUGSFF JG XF XBOU UP

pipelineFn :: Query
-> IO (Either Err [(SomeObj, IoOnlyObj)])
pipelineFn =
(traverse makeIoOnlyObj . mapM decodeFn =<<) . fetchFn

"OE TJODF mapM JT KVTU traverse XJUI B TMJHIUMZ EJƵFSFOU UZQF


$)"15&3  53"7&34"#-& 

pipelineFn :: Query
-> IO (Either Err [(SomeObj, IoOnlyObj)])
pipelineFn = (traverse makeIoOnlyObj
. traverse decodeFn =<<) . fetchFn

5IJT JT UIF UFSTF DMFBO TUZMF NBOZ )BTLFMMFST QSFGFS "T XF


TBJE CBDL XIFO XF ƶSTU JOUSPEVDFE JU QPJOUGSFF TUZMF DBO IFMQ
GPDVT UIF BUUFOUJPO PO UIF GVODUJPOT SBUIFS UIBO UIF TQFDJƶDT
PG UIF EBUB UIBU BSF CFJOH QBTTFE BSPVOE BT BSHVNFOUT 6TJOH
GVODUJPOT MJLF traverse DMFBOT VQ DPEF CZ ESBXJOH BUUFOUJPO UP
UIF XBZT UIF UZQFT BSF DIBOHJOH BOE TJHOBMJOH UIF QSPHSBN
NFSƊT JOUFOU

 %P BMM UIF UIJOHT


8FƊSF HPJOH UP VTF BO )551 DMJFOU MJCSBSZ OBNFE XSFR GPS
UIJT EFNPOTUSBUJPO TP XF DBO NBLF DBMMT UP B IBOEZEBOEZ
XFCTJUF GPS UFTUJOH )551 DMJFOUT BU http://httpbin.org/ 'FFM
GSFF UP FYQFSJNFOU BOE TVCTUJUVUF ZPVS PXO JEFBT GPS )551
TFSWJDFT PS XFCTJUFT ZPV DPVME QPLF BOE QSPE

http://hackage.haskell.org/package/wreq
$)"15&3  53"7&34"#-& 

module HttpStuff where

import Data.ByteString.Lazy hiding (map)


import Network.Wreq

-- replace with other websites


-- if desired or needed
urls :: [String]
urls = [ "http://httpbin.com/ip"
, "http://httpbin.org/bytes/5"
]

mappingGet :: [IO (Response ByteString)]


mappingGet = map get urls

#VU XIBU JG XF EPOƊU XBOU B MJTU PG *0 BDUJPOT XF DBO QFSGPSN


UP HFU B SFTQPOTF CVU SBUIFS POF CJH *0 BDUJPO UIBU QSPEVDFT B
MJTU PG SFTQPOTFT 5IJT JT XIFSF 5SBWFSTBCMF DBO CF IFMQGVM

traversedUrls :: IO [Response ByteString]


traversedUrls = traverse get urls

8F IPQF UIBU UIFTF FYBNQMFT IBWF IFMQFE EFNPOTUSBUF UIBU


5SBWFSTBCMF JT B VTFGVM UZQFDMBTT 8IJMF 'PMEBCMF TFFNT USJWJBM
JU JT B OFDFTTBSZ TVQFSDMBTT PG 5SBWFSTBCMF BOE 5SBWFSTBCMF MJLF
$)"15&3  53"7&34"#-& 

'VODUPS BOE .POBE JT OPX XJEFMZ VTFE JO FWFSZEBZ )BTLFMM


DPEF EVF UP JUT QSBDUJDBMJUZ

4USFOHUI GPS VOEFSTUBOEJOH


5SBWFSTBCMF JT TUSPOHFS UIBO 'VODUPS BOE 'PMEBCMF #FDBVTF PG
UIJT XF DBO SFDPWFS UIF 'VODUPS BOE 'PMEBCMF JOTUBODF GPS B
UZQF GSPN UIF 5SBWFSTBCMF KVTU BT XF DBO SFDPWFS UIF 'VODUPS
BOE "QQMJDBUJWF GSPN UIF .POBE )FSF XF DBO VTF UIF *EFOUJUZ
UZQF UP HFU TPNFUIJOH UIBU JT FTTFOUJBMMZ KVTU GNBQ BMM PWFS
BHBJO

Prelude> import Data.Functor.Identity


Prelude> traverse (Identity . (+1)) [1, 2]
Identity [2,3]
Prelude> runIdentity $ traverse (Identity . (+1)) [1, 2]
[2,3]
Prelude> let edgelordMap f t = runIdentity $ traverse (Identity . f
Prelude> :t edgelordMap
edgelordMap :: Traversable t => (a -> b) -> t a -> t b
Prelude> edgelordMap (+1) [1..5]
[2,3,4,5,6]

6TJOH $POTU PS $POTUBOU XF DBO SFDPWFS B GPME.BQQZ MPPL


JOH 'PMEBCMF BT XFMM

Prelude> import Data.Monoid


$)"15&3  53"7&34"#-& 

-- from `transformers`
Prelude> import Data.Functor.Constant

Prelude> let xs = [1, 2, 3, 4, 5] :: [Sum Integer]


Prelude> traverse (Constant . (+1)) xs
Constant (Sum {getSum = 20})

Prelude> let foldMap' f t = getConstant $ traverse (Constant . f) t


Prelude> :t foldMap'
foldMap' :: (Traversable t, Monoid a) => (a1 -> a) -> t a1 -> a
Prelude> :t foldMap
foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m

%PJOH FYFSDJTFT MJLF UIJT DBO IFMQ TUSFOHUIFO ZPVS JOUVJUJPOT


GPS UIF SFMBUJPOTIJQT PG UIFTF UZQFDMBTTFT BOE UIFJS DBOPOJDBM
GVODUJPOT 8F LOPX JU TPNFUJNFT GFFMT MJLF UIFTF UIJOHT BSF
QVSF JOUFMMFDUVBM FYFSDJTF CVU HFUUJOH DPNGPSUBCMF XJUI NB
OJQVMBUJOH GVODUJPOT MJLF UIFTF JT VMUJNBUFMZ UIF LFZ UP HFUUJOH
DPNGPSUBCMF XJUI )BTLFMM 5IJT JT IPX ZPV MFBSO UP QMBZ UZQF
5FUSJT XJUI UIF QSPT

 5SBWFSTBCMF JOTUBODFT


:PV LOFX UIJT XBT DPNJOH
$)"15&3  53"7&34"#-& 

&JUIFS
5IF 5SBWFSTBCMF JOTUBODF UIBU GPMMPXT IFSF JT JEFOUJDBM UP UIF
POF JO UIF Data.Traversable NPEVMF JO CBTF CVU XFƊWF BEEFE
B 'VODUPS 'PMEBCMF BOE "QQMJDBUJWF TP UIBU ZPV NJHIU TFF B
QSPHSFTTJPO
$)"15&3  53"7&34"#-& 

data Either a b =
Left a
| Right b
deriving (Eq, Ord, Show)

instance Functor (Either a) where


fmap _ (Left x) = Left x
fmap f (Right y) = Right (f y)

instance Applicative (Either e) where


pure = Right
Left e <*> _ = Left e
Right f <*> r = fmap f r

instance Foldable (Either a) where


foldMap _ (Left _) = mempty
foldMap f (Right y) = f y

foldr _ z (Left _) = z
foldr f z (Right y) = f y z

instance Traversable (Either a) where


traverse _ (Left x) = pure (Left x)
traverse f (Right y) = Right <$> f y
$)"15&3  53"7&34"#-& 

(JWFO XIBU ZPVƊWF TFFO BCPWF UIJT IPQFGVMMZ JTOƊU UPP TVS
QSJTJOH 8F IBWF GVODUJPO BQQMJDBUJPO BOE UZQFƷJQQJOH JO BO
&JUIFS DPOUFYU

5VQMF
"T BCPWF XFƊWF QSPWJEFE B QSPHSFTTJPO PG JOTUBODFT CVU GPS
UIF UXPUVQMF PS BOPOZNPVT QSPEVDU

instance Functor ((,) a) where


fmap f (x,y) = (x, f y)

instance Monoid a => Applicative ((,) a) where


pure x = (mempty, x)
(u, f) <*> (v, x) = (u `mappend` v, f x)

instance Foldable ((,) a) where


foldMap f (_, y) = f y
foldr f z (_, y) = f y z

instance Traversable ((,) a) where


traverse f (x, y) = (,) x <$> f y

)FSF XF IBWF NVDI UIF TBNF CVU GPS B UVQMF DPOUFYU


$)"15&3  53"7&34"#-& 

 5SBWFSTBCMF -BXT


5IF USBWFSTF GVODUJPO NVTU TBUJTGZ UIF GPMMPXJOH MBXT

 /BUVSBMJUZ

t . traverse f = traverse (t . f)

5IJT MBX UFMMT VT UIBU GVODUJPO DPNQPTJUJPO CFIBWFT JO


VOTVSQSJTJOH XBZT XJUI SFTQFDU UP B USBWFSTFE GVODUJPO
4JODF B USBWFSTFE GVODUJPO ԕ JT HFOFSBUJOH UIF TUSVDUVSF
UIBU BQQFBST PO UIF ƌPVUTJEFƍ PG UIF USBWFSTF PQFSBUJPO
UIFSFƊT OP SFBTPO XF TIPVMEOƊU CF BCMF UP ƷPBU B GVODUJPO
PWFS UIF TUSVDUVSF JOUP UIF USBWFSTBM JUTFMG

 *EFOUJUZ

traverse Identity = Identity

5IJT MBX TBZT UIBU USBWFSTJOH UIF EBUB DPOTUSVDUPS PG UIF


*EFOUJUZ UZQF PWFS B WBMVF XJMM QSPEVDF UIF TBNF SFTVMU
BT KVTU QVUUJOH UIF WBMVF JO *EFOUJUZ 5IJT UFMMT VT *EFOUJUZ
SFQSFTFOUT B ƌTUSVDUVSBMƍ JEFOUJUZ GPS USBWFSTJOH EBUB 5IJT
JT BOPUIFS XBZ PG TBZJOH UIBU B 5SBWFSTBCMF JOTUBODF DBOOPU
BEE PS JOKFDU BOZ TUSVDUVSF PS ƌFƵFDUTƍ

 $PNQPTJUJPO

traverse (Compose . fmap g . f) =


Compose . fmap (traverse g) . traverse f
$)"15&3  53"7&34"#-& 

5IJT MBX EFNPOTUSBUFT IPX XF DBO DPMMBQTF TFRVFOUJBM


USBWFSTBMT JOUP B TJOHMF USBWFSTBM CZ UBLJOH BEWBOUBHF PG
UIF $PNQPTF EBUBUZQF XIJDI DPNCJOFT TUSVDUVSF

5IF TFRVFODF" GVODUJPO NVTU TBUJTGZ UIF GPMMPXJOH MBXT

 /BUVSBMJUZ

t . sequenceA = sequenceA . fmap t

 *EFOUJUZ

sequenceA . fmap Identity = Identity

 $PNQPTJUJPO

sequenceA . fmap Compose =


Compose . fmap sequenceA . sequenceA

/POF PG UIJT TIPVMEƊWF CFFO UPP TVSQSJTJOH HJWFO XIBU ZPVƊWF


TFFO XJUI traverse

 2VBMJUZ $POUSPM


(SFBU OFXT :PV DBO 2VJDL$IFDL ZPVS 5SBWFSTBCMF JOTUBODFT
BT XFMM TJODF UIFZ IBWF MBXT $POWFOJFOUMZ UIF DIFDLFST MJCSBSZ
XFƊWF CFFO VTJOH BMSFBEZ IBT UIF MBXT GPS VT :PV DBO BEE UIF
GPMMPXJOH UP B NPEVMF BOE DIBOHF UIF UZQF BMJBT UP DIBOHF
XIBU JOTUBODFT BSF CFJOH UFTUFE
$)"15&3  53"7&34"#-& 

type TI = []

main = do
let trigger = undefined :: TI (Int, Int, [Int])
quickBatch (traversable trigger)

 $IBQUFS &YFSDJTFT


5SBWFSTBCMF JOTUBODFT
8SJUF B 5SBWFSTBCMF JOTUBODF GPS UIF EBUBUZQF QSPWJEFE ƶMMJOH
JO BOZ SFRVJSFE TVQFSDMBTTFT 6TF 2VJDL$IFDL UP WBMJEBUF ZPVS
JOTUBODFT

*EFOUJUZ

8SJUF B 5SBWFSTBCMF JOTUBODF GPS *EFOUJUZ

newtype Identity a = Identity a


deriving (Eq, Ord, Show)

instance Traversable Identity where


traverse = undefined

$POTUBOU

newtype Constant a b =
Constant { getConstant :: a }
$)"15&3  53"7&34"#-& 

.BZCF

data Optional a =
Nada
| Yep a

-JTU

data List a =
Nil
| Cons a (List a)

5ISFF

data Three a b c =
Three a b c

5ISFFƊ

data Three' a b =
Three' a b b

5IJTƊMM TVDL
$)"15&3  53"7&34"#-& 

data S n a = S (n a) a

-- to make it easier, we'll give you the constraints.

instance Traversable n => Traversable (S n) where


traverse = undefined

*OTUBODFT GPS 5SFF


5IJT NJHIU CF IBSE 8SJUF UIF GPMMPXJOH JOTUBODFT GPS 5SFF
$)"15&3  53"7&34"#-& 

data Tree a =
Empty
| Leaf a
| Node (Tree a) a (Tree a)
deriving (Eq, Show)

instance Functor Tree where


fmap = undefined

-- foldMap is a bit easier and looks more natural,


-- but you can do foldr too for extra credit.
instance Foldable Tree where
foldMap = undefined

instance Traversable Tree where


traverse = undefined

)JOUT

 'PS foldMap UIJOL 'VODUPS CVU XJUI TPNF .POPJE UISPXO


JO

 'PS traverse UIJOL 'VODUPS CVU XJUI TPNF 'VODUPS UISPXO


JO

/PU B UZQP
$)"15&3  53"7&34"#-& 

 'PMMPXVQ SFTPVSDFT


 +BLVC "SOPME 'PMEBCMF BOE 5SBWFSTBCMF

 5IF &TTFODF PG UIF *UFSBUPS 1BUUFSO +FSFNZ (JCCPOT BOE


#SVOP 0MJWFJSB

 "QQMJDBUJWF 1SPHSBNNJOH XJUI &ƵFDUT $POPS .D#SJEF


BOE 3PTT 1BUFSTPO
$IBQUFS 

3FBEFS

5IF UFBST PG UIF XPSME BSF


B DPOTUBOU RVBOUJUZ 'PS
FBDI POF XIP CFHJOT UP
XFFQ TPNFXIFSF FMTF
BOPUIFS TUPQT 5IF TBNF
JT USVF PG UIF MBVHI

4BNVFM #FDLFUU


$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

 3FBEFS
5IF MBTU UXP DIBQUFST XFSF GPDVTFE PO TPNF UZQFDMBTTFT UIBU
NJHIU TUJMM TFFN TUSBOHF BOE EJƸDVMU UP ZPV 5IF OFYU UISFF
DIBQUFST BSF HPJOH UP GPDVT PO TPNF QBUUFSOT UIBU NJHIU TUJMM
TFFN TUSBOHF BOE EJƸDVMU 'PMEBCMF 5SBWFSTBCMF 3FBEFS 4UBUF
BOE 1BSTFST BSF OPU TUSJDUMZ OFDFTTBSZ UP VOEFSTUBOEJOH BOE
VTJOH )BTLFMM 8F EP IBWF SFBTPOT GPS JOUSPEVDJOH UIFN OPX
CVU UIPTF SFBTPOT NJHIU OPU TFFN DMFBS UP ZPV GPS B XIJMF *G
ZPV EPOƊU RVJUF HSBTQ BMM PG JU PO UIF ƶSTU QBTT UIBUƊT DPNQMFUFMZ
ƶOF 3FBE JU UISPVHI EP ZPVS CFTU XJUI UIF FYFSDJTFT DPNF
CBDL XIFO ZPV GFFM MJLF ZPVƊSF SFBEZ
8IFO XSJUJOH BQQMJDBUJPOT QSPHSBNNFST PǒFO OFFE UP QBTT
BSPVOE TPNF JOGPSNBUJPO UIBU NBZ CF OFFEFE JOUFSNJUUFOUMZ
PS VOJWFSTBMMZ UISPVHIPVU BO FOUJSF BQQMJDBUJPO 8F EPOƊU XBOU
UP TJNQMZ QBTT UIJT JOGPSNBUJPO BT BSHVNFOUT CFDBVTF JU XPVME
CF QSFTFOU JO UIF UZQF PG BMNPTU FWFSZ GVODUJPO 5IJT DBO NBLF
UIF DPEF IBSEFS UP SFBE BOE IBSEFS UP NBJOUBJO 5P BEESFTT
UIJT XF VTF UIF 3FBEFS .POBE
*O UIJT DIBQUFS XF XJMM

Ƒ FYBNJOF UIF 'VODUPS "QQMJDBUJWF BOE .POBE JOTUBODFT


GPS GVODUJPOT

Ƒ MFBSO BCPVU UIF 3FBEFS OFXUZQF

Ƒ TFF TPNF FYBNQMFT PG VTJOH 3FBEFS


$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

 " OFX CFHJOOJOH


8FƊSF HPJOH UP TFU UIJT DIBQUFS VQ B CJU EJƵFSFOUMZ GSPN QSFWJ
PVT DIBQUFST CFDBVTF XFƊSF IPQJOH UIBU UIJT XJMM IFMQ EFNPO
TUSBUF UIBU XIBU XFƊSF EPJOH IFSF JT OPU UIBU EJƵFSFOU GSPN
UIJOHT ZPVƊWF EPOF CFGPSF 4P XFƊSF HPJOH UP TUBSU XJUI TPNF
FYBNQMFT 4UBSU B ƶMF MJLF UIJT

import Control.Applicative

boop = (*2)
doop = (+10)

bip :: Integer -> Integer


bip = boop . doop

8F LOPX UIBU UIF bip GVODUJPO XJMM UBLF POF BSHVNFOU CF
DBVTF PG UIF UZQFT PG boop doop BOE (.) /PUF UIBU JG ZPV EP OPU
TQFDJGZ UIF UZQFT BOE MPBE JU GSPN B ƶMF JU XJMM CF NPOPNPS
QIJD CZ EFGBVMU JG ZPV XJTI UP NBLF bip QPMZNPSQIJD ZPV
NBZ DIBOHF JUT TJHOBUVSF CVU ZPV BMTP OFFE UP TQFDJGZ B QPMZ
NPSQIJD UZQF GPS UIF UXP GVODUJPOT JUƊT CVJMU GSPN 5IF SFTU PG
UIF DIBQUFS XJMM XBJU XIJMF ZPV WFSJGZ UIFTF UIJOHT
8IFO XF BQQMZ bip UP BO BSHVNFOU doop XJMM CF BQQMJFE UP
UIBU BSHVNFOU ƶSTU BOE UIFO UIF SFTVMU PG UIBU XJMM CF QBTTFE
BT JOQVU UP boop 4P GBS OPUIJOH OFX
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

8F DBO BMTP XSJUF UIBU GVODUJPO DPNQPTJUJPO UIJT XBZ

bloop :: Integer -> Integer


bloop = fmap boop doop

8F BSFOƊU BDDVTUPNFE UP GNBQQJOH B GVODUJPO PWFS BOPUIFS


GVODUJPO BOE ZPV NBZ CF XPOEFSJOH XIBU UIF GVODUPSJBM DPO
UFYU IFSF JT #Z ƌGVODUPSJBM DPOUFYUƍ XF NFBO UIF TUSVDUVSF UIBU
UIF GVODUJPO JT CFJOH MJǒFE PWFS JO PSEFS UP BQQMZ UP UIF WBMVF
JOTJEF 'PS FYBNQMF B MJTU JT B GVODUPSJBM DPOUFYU XF DBO MJǒ
GVODUJPOT PWFS 8F TBZ UIBU UIF GVODUJPO HFUT MJǒFE PWFS UIF
TUSVDUVSF PG UIF MJTU BOE BQQMJFE UP PS NBQQFE PWFS UIF WBMVFT
UIBU BSF JOTJEF UIF MJTU
*O bloop UIF DPOUFYU JT B QBSUJBMMZBQQMJFE GVODUJPO "T JO
GVODUJPO DPNQPTJUJPO fmap DPNQPTFT UIF UXP GVODUJPOT CFGPSF
BQQMZJOH UIFN UP UIF BSHVNFOU 5IF SFTVMU PG UIF POF DBO UIFO
HFU QBTTFE UP UIF OFYU BT JOQVU 6TJOH fmap IFSF MJǒT UIF POF
QBSUJBMMZBQQMJFE GVODUJPO PWFS UIF OFYU JO B TFOTF TFUUJOH VQ
TPNFUIJOH MJLF UIJT

fmap boop doop x == (*2) ((+10) x)


-- when this x comes along, it's the
-- first necessary argument to (+10)
-- then the result for that is the
-- first necessary argument to (*2)
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

5IJT JT UIF GVODUPS PG GVODUJPOT 8FƊSF HPJOH UP HP JOUP


NPSF EFUBJM BCPVU UIJT TPPO
'PS OPX MFUƊT UVSO UP BOPUIFS TFU PG FYBNQMFT 1VU UIFTF JO
UIF TBNF ƶMF TP boop BOE doop BSF TUJMM JO TDPQF

bbop :: Integer -> Integer


bbop = (+) <$> boop <*> doop

duwop :: Integer -> Integer


duwop = liftA2 (+) boop doop

/PX XFƊSF JO BO "QQMJDBUJWF DPOUFYU 8FƊWF BEEFE BOPUIFS


GVODUJPO UP MJǒ PWFS UIF DPOUFYUT PG PVS QBSUJBMMZBQQMJFE GVOD
UJPOT 5IJT UJNF XF TUJMM IBWF QBSUJBMMZBQQMJFE GVODUJPOT UIBU
BSF BXBJUJOH BQQMJDBUJPO UP BO BSHVNFOU CVU UIJT XJMM XPSL
EJƵFSFOUMZ UIBO GNBQQJOH EJE 5IJT UJNF UIF BSHVNFOU XJMM
HFU QBTTFE UP CPUI boop BOE doop JO QBSBMMFM BOE UIF SFTVMUT XJMM
CF BEEFE UPHFUIFS
boop BOE doop BSF FBDI XBJUJOH GPS BO JOQVU 8F DBO BQQMZ
UIFN CPUI BU PODF MJLF UIJT

Prelude> bbop 3
19

5IBU EPFT TPNFUIJOH MJLF UIJT


$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

((+) <$> (*2) <*> (+10)) 3

-- First the fmap


(*2) :: Num a => a -> a
(+) :: Num a => a -> a -> a
(+) <$> (*2) :: Num a => a -> a -> a

.BQQJOH B GVODUJPO BXBJUJOH UXP BSHVNFOUT PWFS B GVODUJPO


BXBJUJOH POF QSPEVDFT B UXP BSHVNFOU GVODUJPO
3FNFNCFS UIJT JT JEFOUJDBM UP GVODUJPO DPNQPTJUJPO

(+) . (*2) :: Num a => a -> a -> a

8JUI UIF TBNF SFTVMU

Prelude> ((+) . (*2)) 5 3


13
Prelude> ((+) <$> (*2)) 5 3
13

4P XIBUƊT IBQQFOJOH
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

((+) <$> (*2)) 5 3

-- Keeping in mind that this is (.) under the hood


((+) . (*2)) 5 3

-- f . g = \ x -> f (g x)

((+) . (*2)) == \ x -> (+) (2 * x)

5IF USJDLZ QBSU IFSF JT UIBU FWFO BǒFS XF BQQMZ ԧ XFƊWF HPU
(+) QBSUJBMMZ BQQMJFE UP UIF ƶSTU BSHVNFOU XIJDI XBT EPVCMFE
CZ (*2) 5IFSFƊT B TFDPOE BSHVNFOU BOE UIBUƊT XIBUƊMM HFU
BEEFE UP UIF ƶSTU BSHVNFOU UIBU HPU EPVCMFE

-- The first function to get applied is (*2),


-- and the first argument is 5. (*2) takes one
-- argument, so we get:

((+) . (*2)) 5 3
(\ x -> (+) (2 * x)) 5 3
(\ 5 -> (+) (2 * 5)) 3
((+) 10) 3

-- Then it adds 10 and 3


13
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

0LBZ CVU XIBU BCPVU UIF TFDPOE CJU

((+) <$> (*2) <*> (+10)) 3

-- Wait, what? What happened to the


-- first argument?
((+) <$> (*2) <*> (+10)) :: Num b => b -> b

0OF PG UIF OJDF UIJOHT BCPVU )BTLFMM JT XF DBO BTTFSU B NPSF


DPODSFUF UZQF GPS GVODUJPOT MJLF (<*>) BOE TFF JG UIF DPNQJMFS
BHSFFT XFƊSF QVUUJOH GPSUI TPNFUIJOH IZQPUIFUJDBMMZ QPTTJCMF
-FUƊT SFNJOE PVSTFMWFT PG UIF UZQF PG (<*>)

Prelude> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b

-- in this case, we know f is ((->) a)


-- so we concretize it thusly
Prelude> :t (<*>) :: (a -> a -> b) -> (a -> a) -> (a -> b)
(<*>) :: (a -> a -> b) -> (a -> a) -> (a -> b)

5IF DPNQJMFS BHSFFT UIBU UIJT JT B QPTTJCMF UZQF GPS (<*>)


4P IPX EPFT UIBU XPSL 8IBUƊT IBQQFOJOH JT XFƊSF GFFEJOH
B TJOHMF BSHVNFOU UP UIF (*2) BOE (+10) BOE UIF UXP SFTVMUT
GPSN UIF UXP BSHVNFOUT UP (+)
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

((+) <$> (*2) <*> (+10)) 3

(3*2) + (3+10)

6 + 13

19

8FƊE VTF UIJT XIFO UXP GVODUJPOT XPVME TIBSF UIF TBNF
JOQVU BOE XF XBOU UP BQQMZ TPNF PUIFS GVODUJPO UP UIF SFTVMU
PG UIPTF UP SFBDI B ƶOBM SFTVMU 5IJT IBQQFOT NPSF UIBO ZPV
NJHIU UIJOL BOE XF TBX BO FYBNQMF PG JU CBDL JO UIF "CTUSBDU
4USVDUVSF "QQMJFE DIBQUFS

module Web.Shipping.Utils ((<||>)) where

import Control.Applicative (liftA2)

(<||>) :: (a -> Bool) -> (a -> Bool) -> a -> Bool


(<||>) = liftA2 (||)

5IBU JT UIF TBNF JEFB BT duwop BCPWF


'JOBMMZ BOPUIFS FYBNQMF
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

boopDoop :: Integer -> Integer


boopDoop = do
a <- boop
b <- doop
return (a + b)

5IJT XJMM EP QSFDJTFMZ UIF TBNF UIJOH BT UIF "QQMJDBUJWF


FYBNQMF CVU UIJT UJNF UIF DPOUFYU JT NPOBEJD 5IJT EJTUJODUJPO
EPFTOƊU NVDI NBUUFS XJUI UIJT QBSUJDVMBS GVODUJPO CVU XF LOPX
JU NVTU CF CFDBVTF XFƊWF VTFE do TZOUBY 8F BTTJHO UIF WBSJBCMF
Ԑ UP UIF QBSUJBMMZBQQMJFE GVODUJPO boop BOE ԑ UP doop "T TPPO
BT XF SFDFJWF BO JOQVU JU XJMM ƶMM UIF FNQUZ TMPUT JO boop BOE
doop 5IF SFTVMUT XJMM CF CPVOE UP UIF WBSJBCMFT Ԑ BOE ԑ BOE
QBTTFE JOUP return
4P XFƊWF TFFO IFSF UIBU XF DBO IBWF B Functor Applicative
BOE Monad GPS QBSUJBMMZBQQMJFE GVODUJPOT *O BMM DBTFT UIFTF
BSF BXBJUJOH BQQMJDBUJPO UP POF BSHVNFOU UIBU XJMM BMMPX CPUI
GVODUJPOT UP CF FWBMVBUFE
5IJT JT UIF JEFB PG 3FBEFS *U JT B XBZ PG TUSJOHJOH GVODUJPOT
UPHFUIFS XIFO BMM UIPTF GVODUJPOT BSF BXBJUJOH POF JOQVU GSPN
B TIBSFE FOWJSPONFOU 8FƊSF HPJOH UP HFU JOUP UIF EFUBJMT
PG IPX JU XPSLT CVU UIF JNQPSUBOU JOUVJUJPO IFSF JT UIBU JUƊT
KVTU BOPUIFS XBZ PG BCTUSBDUJOH PVU GVODUJPO BQQMJDBUJPO BOE
HJWFT VT B XBZ UP EP DPNQVUBUJPO JO UFSNT PG BO BSHVNFOU
UIBU IBTOƊU CFFO TVQQMJFE ZFU 8F VTF UIJT NPTU PǒFO XIFO
XF IBWF B DPOTUBOU WBMVF UIBU XF XJMM PCUBJO GSPN TPNFXIFSF
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

PVUTJEF PVS QSPHSBN UIBU XJMM CF BO BSHVNFOU UP B XIPMF CVODI


PG GVODUJPOT 6TJOH 3FBEFS BMMPXT VT UP BWPJE QBTTJOH UIBU
BSHVNFOU BSPVOE FYQMJDJUMZ

4IPSU &YFSDJTF 8BSNJOH 6Q


8FƊMM CF EPJOH TPNFUIJOH IFSF WFSZ TJNJMBS UP XIBU ZPV TBX
BCPWF UP HJWF ZPV QSBDUJDF BOE USZ UP EFWFMPQ B GFFM PS JOUVJUJPO
GPS XIBU JT UP DPNF 5IFTF BSF TJNJMBS FOPVHI UP XIBU ZPV KVTU
TBX UIBU ZPV DBO BMNPTU DPQZ BOE QBTUF TP USZ OPU UP PWFSUIJOL
UIFN UPP NVDI
'JSTU TUBSU B ƶMF PƵ MJLF UIJT

import Data.Char

cap :: [Char] -> [Char]


cap xs = map toUpper xs

rev :: [Char] -> [Char]


rev xs = reverse xs

5XP TJNQMF GVODUJPOT XJUI UIF TBNF UZQF UBLJOH UIF TBNF
UZQF PG JOQVU 8F DPVME DPNQPTF UIFN VTJOH (.) PS fmap
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

composed :: [Char] -> [Char]


composed = undefined

fmapped :: [Char] -> [Char]


fmapped = undefined

5IF PVUQVU PG UIPTF UXP TIPVME CF JEFOUJDBM POF TUSJOH UIBU


JT NBEF BMM VQQFSDBTF BOE SFWFSTFE MJLF UIJT

Prelude> composed "Julie"


"EILUJ"
Prelude> fmapped "Chris"
"SIRHC"

/PX XF XBOU UP SFUVSO UIF SFTVMUT PG cap BOE rev CPUI BT B


UVQMF MJLF UIJT

Prelude> tupled "Julie"


("JULIE","eiluJ")
-- or
Prelude> tupled' "Julie"
("eiluJ","JULIE")

8F XJMM XBOU UP VTF BO BQQMJDBUJWF IFSF 5IF UZQF XJMM MPPL


MJLF UIJT

tupled :: [Char] -> ([Char], [Char])


$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

5IFSF JT OP TQFDJBM SFBTPO TVDI B GVODUJPO OFFET UP CF


NPOBEJD CVU MFUƊT EP UIBU UPP UP HFU TPNF QSBDUJDF %P JU
POF UJNF VTJOH do TZOUBY UIFO USZ XSJUJOH B OFX WFSTJPO VTJOH
(>>=) 5IF UZQFT XJMM CF UIF TBNF BT UIF UZQF GPS tupled

 5IJT JT 3FBEFS


"T XF TBX BCPWF GVODUJPOT IBWF 'VODUPS "QQMJDBUJWF BOE
.POBE JOTUBODFT 6TVBMMZ XIFO ZPV TFF PS IFBS UIF UFSN
3FBEFS JUƊMM CF SFGFSSJOH UP UIF .POBE PS "QQMJDBUJWF JOTUBODFT
8F VTF GVODUJPO DPNQPTJUJPO CFDBVTF JU MFUT VT DPNQPTF
UXP GVODUJPOT XJUIPVU FYQMJDJUMZ IBWJOH UP SFDPHOJ[F UIF BS
HVNFOU UIBU XJMM FWFOUVBMMZ BSSJWF UIF 'VODUPS PG GVODUJPOT
JT GVODUJPO DPNQPTJUJPO 8JUI UIF 'VODUPS PG GVODUJPOT XF
BSF BCMF UP NBQ BO PSEJOBSZ GVODUJPO PWFS BOPUIFS UP DSFBUF B
OFX GVODUJPO BXBJUJOH B ƶOBM BSHVNFOU 5IF "QQMJDBUJWF BOE
.POBE JOTUBODFT GPS UIF GVODUJPO UZQF HJWF VT B XBZ UP NBQ
B GVODUJPO UIBU JT BXBJUJOH BO Ԑ PWFS BOPUIFS GVODUJPO UIBU JT
BMTP BXBJUJOH BO Ԑ
(JWJOH JU B OBNF IFMQT VT LOPX UIF XIBU BOE XIZ PG XIBU
XFƊSF EPJOH SFBEJOH BO BSHVNFOU GSPN UIF FOWJSPONFOU JOUP
GVODUJPOT *UƊMM CF FTQFDJBMMZ OJDF GPS DMBSJUZƊT TBLF MBUFS XIFO
XF NBLF UIF 3FBEFS NPOBE USBOTGPSNFS
&YDJUJOH SJHIU -FUƊT CBDL VQ IFSF BOE HP JOUP NPSF EFUBJM
BCPVU IPX 3FBEFS XPSLT
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

 #SFBLJOH EPXO UIF 'VODUPS PG


GVODUJPOT
*G ZPV CSJOH VQ :info Functor JO ZPVS 3&1- POF PG UIF JO
TUBODFT ZPV NJHIU OPUJDF JT UIF POF GPS UIF QBSUJBMMZBQQMJFE
UZQF DPOTUSVDUPS PG GVODUJPOT ((->) r)

instance Functor ((->) r)

5IJT DBO CF B MJUUMF DPOGVTJOH TP XFƊSF HPJOH UP VOXJOE JU


VOUJM IPQFGVMMZ JUƊT B CJU NPSF DPNGPSUBCMF 'JSTU MFUƊT TFF XIBU
XF DBO BDDPNQMJTI XJUI UIJT

Prelude> fmap (+1) (*2) 3


7

-- Rearranging a little bit syntactically


Prelude> fmap (+1) (*2) $ 3
7

Prelude> (fmap (+1) (*2)) 3


7

5IJT TIPVME MPPL GBNJMJBS

Prelude> (+1) . (*2) $ 3


7
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

Prelude> (+2) . (*1) $ 2


4

Prelude> fmap (+2) (*1) $ 2


4

Prelude> (+2) `fmap` (*1) $ 2


4

'PSUVOBUFMZ UIFSFƊT OPUIJOH XFJSE HPJOH PO IFSF *G ZPV


DIFDL UIF JNQMFNFOUBUJPO PG UIF JOTUBODF JO CBTF ZPVƊMM ƶOE
UIF GPMMPXJOH

instance Functor ((->) r) where


fmap = (.)

-FUƊT VOSBWFM UIF UZQFT UIBU TFFN TP VOVTVBM IFSF 3FNFN


CFS UIBU (->) UBLFT UXP BSHVNFOUT BOE UIFSFGPSF IBT LJOE * ->
* -> * 4P XF LOPX VQGSPOU UIBU XF IBWF UP BQQMZ POF PG UIF
UZQF BSHVNFOUT CFGPSF XF DBO IBWF B 'VODUPS 8JUI UIF Either
'VODUPS XF LOPX UIBU XF XJMM MJǒ PWFS UIF Either a BOE JG PVS
GVODUJPO XJMM CF BQQMJFE JU XJMM CF BQQMJFE UP UIF ԑ WBMVF 8JUI
UIF GVODUJPO UZQF

data (->) a b
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

UIF TBNF SVMF BQQMJFT ZPV IBWF UP MJǒ PWFS UIF (->) a BOE
POMZ USBOTGPSN UIF ԑ WBMVF 5IF Ԑ JT DPOWFOUJPOBMMZ DBMMFE ԡ
GPS 3FBEFS JO UIFTF JOTUBODFT CVU B UZQF WBSJBCMF PG BOZ PUIFS
OBNF TNFMMT BT TXFFU )FSF r JT UIF ƶSTU BSHVNFOU PG (a -> b)

-- Type constructor of functions


(->)
-- Fully applied
a -> b

((->) r)
-- is
r ->

-- so r is the type of the


-- argument to the function

'SPN UIJT XF DBO EFUFSNJOF UIBU ԡ UIF BSHVNFOU UZQF GPS


GVODUJPOT JT QBSU PG UIF TUSVDUVSF CFJOH MJǕFE PWFS XIFO XF MJǒ
PWFS B GVODUJPO OPU UIF WBMVF CFJOH USBOTGPSNFE PS NBQQFE
PWFS
5IJT MFBWFT UIF SFTVMU PG UIF GVODUJPO BT UIF WBMVF CFJOH
USBOTGPSNFE 5IJT IBQQFOT UP MJOF VQ OFBUMZ XJUI XIBU GVOD
UJPO DPNQPTJUJPO JT BCPVU
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

(.) :: (b -> c) -> (a -> b) -> a -> c


-- or perhaps
(.) :: (b -> c) -> (a -> b) -> (a -> c)

/PX IPX EPFT UIJT MJOF VQ XJUI 'VODUPS


$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

(.) :: (b -> c) -> (a -> b) -> (a -> c)

fmap :: Functor f => (a -> b) -> f a -> f b

-- we're going to remove the names of the functions


-- and the typeclass constraint as we can take it for
-- granted from here on out.

:: (b -> c) -> (a -> b) -> (a -> c)


:: (a -> b) -> f a -> f b

-- Changing up the letters without changing the meaning

:: (b -> c) -> (a -> b) -> (a -> c)


:: (b -> c) -> f b -> f c

-- f is ((->) a)

:: (b -> c) -> (a -> b) -> (a -> c)


:: (b -> c) -> ((->) a) b -> ((->) a) c

-- Unroll the prefix notation into infix

:: (b -> c) -> (a -> b) -> (a -> c)


:: (b -> c) -> (a -> b) -> (a -> c)
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

#BEB CJOH 'VODUPSJBM MJǒJOH GPS GVODUJPOT

 #VU VI 3FBEFS


"I ZFT SJHIU 3FBEFS JT B OFXUZQF XSBQQFS GPS UIF GVODUJPO
UZQF

newtype Reader r a =
Reader { runReader :: r -> a }

5IF ԡ JT UIF UZQF XFƊSF ƌSFBEJOHƍ JO BOE Ԑ JT UIF SFTVMU UZQF


PG PVS GVODUJPO
5IF 3FBEFS OFXUZQF IBT B IBOEZ runReader BDDFTTPS UP HFU
UIF GVODUJPO PVU PG 3FBEFS -FU VT QSPWF GPS PVSTFMWFT UIBU
UIJT JT UIF TBNF UIJOH CVU XJUI B UPVDI PG EBUB DPOTUSVDUPS
KJHHFSZQPLFSZ NJYFE JO 8IBU EPFT UIF 'VODUPS GPS UIJT MPPL
MJLF DPNQBSFE UP GVODUJPO DPNQPTJUJPO
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

instance Functor (Reader r) where


fmap :: (a -> b) -> Reader r a -> Reader r b
fmap f (Reader ra) =
Reader $ \r -> f (ra r)

-- same as (.)
compose :: (b -> c) -> (a -> b) -> (a -> c)
compose f g = \x -> f (g x)

-- see it?
\r -> f (ra r)
\x -> f (g x)

#BTJDBMMZ UIF TBNF UIJOH SJHIU


8F DBO VTF UIF GBDU UIBU XF SFDPHOJ[F UIJT BT GVODUJPO DPN
QPTJUJPO UP NBLF B TMJHIUMZ EJƵFSFOU JOTUBODF GPS 3FBEFS

instance Functor (Reader r) where


fmap :: (a -> b) -> Reader r a -> Reader r b
fmap f (Reader ra) =
Reader $ (f . ra)

4P XIBU XFƊSF EPJOH IFSF JT CBTJDBMMZ

 6OQBDL r -> a PVU PG 3FBEFS

 $PNQPTF ԕ XJUI UIF GVODUJPO XF VOQBDLFE PVU PG 3FBEFS


$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

 1VU UIF OFX GVODUJPO NBEF GSPN UIF DPNQPTJUJPO CBDL


JOUP 3FBEFS

8JUIPVU UIF 3FBEFS OFXUZQF XF ESPQ TUFQT  BOE  BOE


IBWF GVODUJPO DPNQPTJUJPO

&YFSDJTF "TL
*NQMFNFOU UIF GPMMPXJOH GVODUJPO *G ZPV HFU TUVDL SFNFN
CFS JUƊT MFTT DPNQMJDBUFE UIBO JU MPPLT 8SJUF EPXO XIBU ZPV
LOPX 8IBU EP ZPV LOPX BCPVU UIF UZQF Ԑ 8IBU EPFT UIF
UZQF TJNQMJGZ UP )PX NBOZ JOIBCJUBOUT EPFT UIBU UZQF IBWF
:PVƊWF TFFO UIF UZQF CFGPSF

ask :: Reader a a
ask = Reader ???

 'VODUJPOT IBWF BO "QQMJDBUJWF UPP


8FƊWF TFFO B DPVQMF PG FYBNQMFT BMSFBEZ PG UIF "QQMJDBUJWF PG
GVODUJPOT BOE IPX JU XPSLT /PX XFƊMM HFU JOUP UIF EFUBJMT
5IF ƶSTU UIJOH XF XBOU UP EP JT OPUJDF IPX UIF UZQFT TQF
DJBMJ[F
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

-- Applicative f =>

-- f ~ (->) r

pure :: a -> f a
pure :: a -> (r -> a)

(<*>) :: f (a -> b) -> f a -> f b


(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)

"T XF TBX JO UIF 'VODUPS JOTUBODF UIF ԡ PG 3FBEFS JT QBSU PG


UIF ԕ TUSVDUVSF 8F IBWF UXP BSHVNFOUT JO UIJT GVODUJPO BOE
CPUI PG UIFN BSF GVODUJPOT XBJUJOH GPS UIF ԡ JOQVU 8IFO UIBU
DPNFT CPUI GVODUJPOT XJMM CF BQQMJFE UP SFUVSO B ƶOBM SFTVMU
PG ԑ

%FNPOTUSBUJOH UIF GVODUJPO BQQMJDBUJWF


5IJT FYBNQMF JT TJNJMBS UP PUIFS EFNPOTUSBUJPOT XFƊWF EPOF
QSFWJPVTMZ JO UIF CPPL CVU UIJT UJNF XFƊMM CF BJNJOH UP TIPX
ZPV XIBU TQFDJƶD VTF UIF "QQMJDBUJWF PG GVODUJPOT UZQJDBMMZ
IBT 8F TUBSU XJUI TPNF OFXUZQFT GPS USBDLJOH PVS EJƵFSFOU
4USJOH WBMVFT
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

newtype HumanName =
HumanName String
deriving (Eq, Show)

newtype DogName =
DogName String
deriving (Eq, Show)

newtype Address =
Address String
deriving (Eq, Show)

8F EP UIJT TP UIBU PVS UZQFT BSF NPSF TFMGFYQMBOBUPSZ UP


FYQSFTT JOUFOU BOE TP XF EPOƊU BDDJEFOUBMMZ NJY VQ PVS JOQVUT
" UZQF MJLF UIJT

String -> String -> String

SFBMMZ TVDLT XIFO

 5IFZ BSFOƊU TUSJDUMZ BOZ TUSJOH WBMVF

 5IFZ BSFOƊU QSPDFTTFE JO BO JEFOUJDBM GBTIJPO :PV EPOƊU


IBOEMF BEESFTTFT UIF TBNF BT OBNFT

4P NBLF UIF EJƵFSFODF FYQMJDJU


8FƊMM NBLF UXP SFDPSE UZQFT
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

data Person =
Person {
humanName :: HumanName
, dogName :: DogName
, address :: Address
} deriving (Eq, Show)

data Dog =
Dog {
dogsName :: DogName
, dogsAddress :: Address
} deriving (Eq, Show)

5IF GPMMPXJOH BSF NFSFMZ TPNF TBNQMF EBUB UP VTF :PV DBO
NPEJGZ UIFN BT ZPVƊE MJLF

pers :: Person
pers =
Person (HumanName "Big Bird")
(DogName "Barkley")
(Address "Sesame Street")

chris :: Person
chris = Person (HumanName "Chris Allen")
(DogName "Papu")
(Address "Austin")
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

"OE IFSF JT IPX XFƊE XSJUF JU XJUI BOE XJUIPVU 3FBEFS

-- without Reader
getDog :: Person -> Dog
getDog p =
Dog (dogName p) (address p)

-- with Reader
getDogR :: Person -> Dog
getDogR =
Dog <$> dogName <*> address

5IF QBUUFSO PG VTJOH "QQMJDBUJWF JO UIJT NBOOFS JT DPNNPO


TP UIFSFƊT BO BMUFSOBUF XBZ UP EP UIJT VTJOH liftA2

import Control.Applicative (liftA2)

-- with Reader, alternate


getDogR' :: Person -> Dog
getDogR' =
liftA2 Dog dogName address

)FSFƊT UIF UZQF PG MJǒ"

liftA2 :: Applicative f =>


(a -> b -> c)
-> f a -> f b -> f c
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

"HBJO XFƊSF XBJUJOH GPS BO JOQVU GSPN FMTFXIFSF 3BUIFS


UIBO IBWJOH UP UISFBE UIF BSHVNFOU UISPVHI PVS GVODUJPOT
XF FMJEF JU BOE MFU UIF UZQFT NBOBHF JU GPS VT

&YFSDJTF 3FBEJOH $PNQSFIFOTJPO


 8SJUF liftA2 ZPVSTFMG 5IJOL BCPVU JU JO UFSNT PG BCTUSBDU
JOH PVU UIF EJƵFSFODF CFUXFFO getDogR BOE getDogR' JG UIBU
IFMQT

myLiftA2 :: Applicative f =>


(a -> b -> c)
-> f a -> f b -> f c
myLiftA2 = undefined

 8SJUF UIF GPMMPXJOH GVODUJPO "HBJO JU JT TJNQMFS UIBO JU


MPPLT

asks :: (r -> a) -> Reader r a


asks f = Reader ???

 *NQMFNFOU UIF "QQMJDBUJWF GPS 3FBEFS


5P XSJUF UIF "QQMJDBUJWF JOTUBODF GPS 3FBEFS XFƊMM VTF
B QSBHNB DBMMFE InstanceSigs *UƊT BO FYUFOTJPO XF OFFE
JO PSEFS UP BTTFSU B UZQF GPS UIF UZQFDMBTT NFUIPET :PV
PSEJOBSJMZ DBOOPU BTTFSU UZQF TJHOBUVSFT JO JOTUBODFT 5IF
DPNQJMFS BMSFBEZ LOPXT UIF UZQF PG UIF GVODUJPOT TP JUƊT
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

OPU VTVBMMZ OFDFTTBSZ UP BTTFSU UIF UZQFT JO JOTUBODFT BOZ


XBZ 8F EJE UIJT GPS UIF TBLF PG DMBSJUZ UP NBLF UIF 3FBEFS
UZQF FYQMJDJU JO PVS TJHOBUVSFT

-- you'll need this pragma


{-# LANGUAGE InstanceSigs #-}

instance Applicative (Reader r) where


pure :: a -> Reader r a
pure a = Reader $ ???

(<*>) :: Reader r (a -> b)


-> Reader r a
-> Reader r b
(Reader rab) <*> (Reader ra) =
Reader $ \r -> ???

4PNF JOTUSVDUJPOT BOE IJOUT

B
8IFO XSJUJOH UIF pure GVODUJPO GPS 3FBEFS SFNFNCFS
UIBU XIBU ZPVƊSF USZJOH UP DPOTUSVDU JT B GVODUJPO UIBU
UBLFT B WBMVF PG UZQF ԡ XIJDI ZPV LOPX OPUIJOH BCPVU
BOE SFUVSO B WBMVF PG UZQF Ԑ (JWFO UIBU ZPVƊSF OPU
SFBMMZ EPJOH BOZUIJOH XJUI ԡ UIFSFƊT SFBMMZ POMZ POF
UIJOH ZPV DBO EP
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

C
8F HPU UIF EFƶOJUJPO PG UIF BQQMZ GVODUJPO TUBSUFE GPS
ZPV XFƊMM EFTDSJCF XIBU ZPV OFFE UP EP BOE ZPV XSJUF
UIF DPEF *G ZPV VOQBDL UIF UZQF PG 3FBEFSƊT BQQMZ
BCPWF ZPV HFU UIF GPMMPXJOH

<*> :: (r -> a -> b)


-> (r -> a)
-> (r -> b)

-- contrast this with the type of fmap

fmap :: (a -> b)
-> (r -> a)
-> (r -> b)
4P XIBUƊT UIF EJƵFSFODF 5IF EJƵFSFODF JT UIBU BQQMZ
VOMJLF fmap BMTP UBLFT BO BSHVNFOU PG UZQF ԡ
.BLF JU TP

 5IF .POBE PG GVODUJPOT


'VODUJPOT BMTP IBWF B .POBE JOTUBODF :PV TBX UIJT JO UIF CF
HJOOJOH PG UIJT DIBQUFS BOE ZPV QFSIBQT IBWF TPNF JOUVJUJPO
OPX GPS IPX UIJT NVTU XPSL 8FƊSF HPJOH UP XBML UISPVHI B
TJNQMJƶFE EFNPOTUSBUJPO PG IPX JU XPSLT CFGPSF XF HFU UP UIF
UZQFT BOE JOTUBODF 'FFM GSFF UP XPSL UISPVHI UIJT TFDUJPO BT
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

RVJDLMZ PS TMPXMZ BT ZPV UIJOL BQQSPQSJBUF UP ZPVS PXO HSBTQ


PG XIBU XFƊWF QSFTFOUFE TP GBS
-FUƊT TUBSU CZ TVQQPTJOH UIBU XF DPVME XSJUF B DPVQMF PG
TJNQMF GVODUJPOT MJLF TP

foo :: (Functor f, Num a) => f a -> f a


foo r = fmap (+1) r

bar :: Foldable f => t -> f a -> (t, Int)


bar r t = (r, length t)

/PX BT JU IBQQFOT JO PVS QSPHSBN XF XBOU UP NBLF POF


GVODUJPO UIBU XJMM EP CPUI ƈ JODSFNFOU UIF WBMVFT JOTJEF PVS
TUSVDUVSF BOE BMTP UFMM VT UIF MFOHUI PG UIF WBMVF 8F DPVME
XSJUF UIBU MJLF UIJT

froot :: Num a => [a] -> ([a], Int)


froot r = (map (+1) r, length r)

0S XF DPVME XSJUF UIF TBNF GVODUJPO CZ DPNCJOJOH UIF


UXP GVODUJPOT XF BMSFBEZ IBE "T JU JT XSJUUFO BCPWF bar UBLFT
UXP BSHVNFOUT 8F DPVME XSJUF B WFSTJPO UIBU UBLFT POMZ POF
BSHVNFOU TP UIBU CPUI QBSUT PG UIF UVQMF BQQMZ UP UIF TBNF
BSHVNFOU 5IBU JT FBTZ FOPVHI UP EP OPUJDF UIF DIBOHF JO UIF
UZQF TJHOBUVSF BT XFMM


barOne :: Foldable t => t a -> (t a, Int)


barOne r = (r, length r)
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

5IBU HBWF VT UIF SFEVDUJPO UP POF BSHVNFOU UIBU XF XBOUFE


CVU EJEOƊU JODSFNFOU UIF WBMVFT JO UIF MJTU BT PVS foo GVODUJPO
EPFT 8F DBO BEE UIBU UIJT XBZ

barPlus r = (foo r, length r)

#VU XF DBO BMTP EP UIBU NPSF DPNQBDUMZ CZ NBLJOH (foo r)


UIF ƶSTU BSHVNFOU UP bar

frooty :: Num a => [a] -> ([a], Int)


frooty r = bar (foo r) r

/PX XF IBWF BO FOWJSPONFOU JO XIJDI UXP GVODUJPOT BSF


XBJUJOH GPS UIF TBNF BSHVNFOU UP DPNF JO 5IFZƊMM CPUI BQQMZ
UP UIBU BSHVNFOU JO PSEFS UP QSPEVDF B ƶOBM SFTVMU
-FUƊT NBLF B TNBMM DIBOHF UP NBLF JU MPPL B MJUUMF NPSF
3FBEFSZ

frooty' :: Num a => [a] -> ([a], Int)


frooty' = \r -> bar (foo r) r

5IFO XF BCTUSBDU UIJT PVU TP UIBU JUƊT OPU TQFDJƶD UP UIFTF


GVODUJPOT

fooBind m k = \r -> k (m r) r

*O UIJT WFSZ QPMZNPSQIJD WFSTJPO UIF UZQF TJHOBUVSF XJMM


MPPL MJLF UIJT
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

fooBind :: (t2 -> t1) -> (t1 -> t2 -> t) -> t2 -> t

4P NBOZ ԣ UZQFT 5IBUƊT CFDBVTF XF DBOƊU LOPX WFSZ NVDI


BCPVU UIPTF UZQFT PODF PVS GVODUJPO JT UIBU BCTUSBDU 8F DBO
NBLF JU B MJUUMF NPSF DMFBS CZ NBLJOH TPNF TVCTUJUVUJPOT 8FƊMM
VTF UIF ԡ UP SFQSFTFOU UIF BSHVNFOU UIBU CPUI PG PVS GVODUJPOT
BSF XBJUJOH PO ƈ UIF 3FBEFSZ QBSU

fooBind :: (r -> a) -> (a -> r -> b) -> (r -> b)

*G XF DPVME UBLF UIF ԡ QBSUT PVU XF NJHIU OPUJDF UIBU fooBind


JUTFMG MPPLT MJLF B WFSZ BCTUSBDU BOE TJNQMJƶFE WFSTJPO PG TPNF
UIJOH XFƊWF TFFO CFGPSF PWFSQBSFOUIFTJ[JOH B CJU GPS DMBSJUZ


(>>=) :: Monad m => m a -> (a -> (m b)) -> m b


(r -> a) -> (a -> (r -> b)) -> (r -> b)

5IJT JT IPX XF HFU UP UIF .POBE PG GVODUJPOT +VTU BT XJUI


UIF 'VODUPS BOE "QQMJDBUJWF JOTUBODFT UIF ((->) r) JT PVS TUSVD
UVSF ƈ UIF Ԝ JO UIF UZQF PG (>>=) *O UIF OFYU TFDUJPO XFƊMM
XPSL GPSXBSE GSPN UIF UZQFT

5IF .POBE JOTUBODF


"T XF OPUFE UIF ԡ BSHVNFOU SFNBJOT QBSU PG PVS NPOBEJD

TUSVDUVSF
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

(>>=) :: Monad m => m a -> (a -> m b) -> m b


(>>=) :: (->) r a -> (a -> (->) r b) -> (->) r b

(>>=) :: (r -> a) -> (a -> r -> b) -> r -> b

return :: Monad m => a -> m a


return :: a -> (->) r a
return :: a -> r -> a

:PV NBZ OPUJDF UIBU return MPPLT MJLF B GVODUJPO XFƊWF TFFO
B MPU PG JO UIJT CPPL
-FUƊT MPPL BU JU TJEF CZ TJEF XJUI UIF "QQMJDBUJWF

(<*>) :: (->) r (a -> b) -> (->) r a -> (->) r b


(>>=) :: (->) r a -> (a -> (->) r b) -> (->) r b

4P ZPVƊWF HPU UIJT FWFSQSFTFOU UZQF ԡ GPMMPXJOH ZPVS GVOD


UJPOT BSPVOE MJLF B MPOFMZ QVQQZ

&YBNQMF VTFT PG UIF 3FBEFS UZQF


3FNFNCFS UIF FBSMJFS FYBNQMF XJUI 1FSTPO BOE %PH )FSFƊT
UIF TBNF CVU XJUI UIF 3FBEFS .POBE BOE do TZOUBY
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

-- with Reader Monad


getDogRM :: Person -> Dog
getDogRM = do
name <- dogName
addy <- address
return $ Dog name addy

&YFSDJTF 3FBEFS .POBE


 *NQMFNFOU UIF 3FBEFS .POBE

-- Don't forget instancesigs.

instance Monad (Reader r) where


return = pure

(>>=) :: Reader r a
-> (a -> Reader r b)
-> Reader r b
(Reader ra) >>= aRb =
Reader $ \r -> ???

)JOU DPOTUSBTU UIF UZQF XJUI UIF "QQMJDBUJWF JOTUBODF BOE


QFSGPSN UIF NPTU PCWJPVT DIBOHF ZPV DBO JNBHJOF UP
NBLF JU XPSL

 3FXSJUF UIF NPOBEJD getDogRM UP VTF ZPVS 3FBEFS EBUBUZQF


$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

 3FBEFS .POBE CZ JUTFMG JT LJOEB


CPSJOH
*U DBOƊU EP BOZUIJOH UIF "QQMJDBUJWF DBOOPU
3FNFNCFS IPX XF DBMDVMBUFE UIF DBSEJOBMJUZ PG UZQFT

{-# LANGUAGE NoImplicitPrelude #-}

module PrettyReader where

flip :: (a -> b -> c) -> (b -> a -> c)


flip f a b = f b a

const :: a -> b -> a


const a b = a

(.) :: (b -> c) -> (a -> b) -> (a -> c)


f . g = \a -> f (g a)
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

class Functor f where


fmap :: (a -> b) -> f a -> f b

class Functor f => Applicative f where


pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b

class Applicative f => Monad f where


return :: a -> f a

(>>=) :: f a -> (a -> f b) -> f b

instance Functor ((->) r) where


fmap = (.)

instance Applicative ((->) r) where


pure = const

f <*> a = \r -> f r (a r)

instance Monad ((->) r) where


return = pure
m >>= k = flip k <*> m

4QFBLJOH HFOFSBMMZ JO UFSNT PG UIF BMHFCSBT BMPOF ZPV DBO


OPU HFU B .POBE JOTUBODF GSPN UIF "QQMJDBUJWF :PV DBO HFU BO
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

"QQMJDBUJWF GSPN UIF .POBE )PXFWFS PVS JOTUBODFT BCPWF


BSFOƊU JO UFSNT PG BO BCTUSBDU EBUBUZQF XF LOPX JUƊT UIF UZQF PG
GVODUJPOT #FDBVTF JUƊT OPU IJEJOH CFIJOE B 3FBEFS OFXUZQF
XF DBO VTF flip BOE apply UP NBLF UIF .POBE JOTUBODF 8F
OFFE TQFDJƶD UZQF JOGPSNBUJPO UP BVHNFOU XIBU UIF "QQMJDB
UJWF JT DBQBCMF PG CFGPSF XF DBO HFU PVS .POBE JOTUBODF
5IF JEFB UP EFƶOF UIF .POBE JOTUBODF PG GVODUJPOT JO UFSNT
PG UIF "QQMJDBUJWF VTJOH flip BOE apply JT DPVSUFTZ PG +PTFQI
5FM "CSBIBNTPO

 :PV DBO DIBOHF XIBU DPNFT CFMPX


CVU OPU BCPWF
5IF ƌSFBEPOMZƍ OBUVSF PG UIF UZQF BSHVNFOU ԡ NFBOT UIBU ZPV
DBO TXBQ JO B EJƵFSFOU UZQF PS WBMVF PG ԡ GPS GVODUJPOT UIBU
ZPV DBMM CVU OPU GPS GVODUJPOT UIBU DBMM ZPV 5IF CFTU XBZ UP
EFNPOTUSBUF UIJT JT XJUI UIF XJUI3FBEFS5 GVODUJPO XIJDI MFUT
VT TUBSU B OFX 3FBEFS DPOUFYU XJUI B EJƵFSFOU BSHVNFOU CFJOH
QSPWJEFE
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

withReaderT
:: (r' -> r)
-- ^ The function to modify the environment.
-> ReaderT r m a
-- ^ Computation to run in the modified environment.
-> ReaderT r' m a
withReaderT f m = ReaderT $ runReaderT m . f

*O UIF OFYU DIBQUFS XFƊMM TFF UIF 4UBUF NPOBE XIFSF XF DBO
OPU POMZ SFBE JO B WBMVF CVU QSPWJEF B OFX POF XIJDI XJMM
DIBOHF UIF WBMVF DBSSJFE CZ UIF GVODUJPOT UIBU DBMMFE VT OPU
POMZ UIPTF XF DBMMFE

 :PV UFOE UP TFF 3FBEFS5 OPU


3FBEFS
3FBEFS SBSFMZ TUBOET BMPOF 6TVBMMZ JUƊT POF .POBE JO B TUBDL PG
NVMUJQMF UZQFT QSPWJEJOH B .POBE JOTUBODF TVDI BT XJUI B XFC
BQQMJDBUJPO UIBU VTFT 3FBEFS UP HJWF ZPV BDDFTT UP DPOUFYU BCPVU
UIF )551 SFRVFTU 8IFO VTFE JO UIBU GBTIJPO JUƊT B NPOBE
USBOTGPSNFS BOE XF QVU B MFUUFS 5 BǒFS UIF UZQF UP JOEJDBUF
XIFO XFƊSF VTJOH JU BT TVDI TP ZPVƊMM VTVBMMZ TFF 3FBEFS5 JO
QSPEVDUJPO )BTLFMM DPEF SBUIFS UIBO 3FBEFS
'VSUIFS B 3FBEFS PG *OU JTOƊU SFBMMZ BMM UIBU VTFGVM PS DPN
QFMMJOH 6TVBMMZ JG ZPV IBWF B 3FBEFS JUƊT PG B SFDPSE PG TFWFSBM
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

QPTTJCMZ NBOZ
WBMVFT UIBU ZPVƊSF HFUUJOH PVU PG UIF 3FBEFS

 $IBQUFS &YFSDJTFT


" XBSNVQ TUSFUDI
5IFTF FYFSDJTFT BSF EFTJHOFE UP CF B XBSNVQ BOE HFU ZPV
VTJOH TPNF PG UIF TUVƵ XFƊWF MFBSOFE JO UIF MBTU GFX DIBQUFST
8IJMF UIFTF FYFSDJTFT DPNQSJTF DPEF GSBHNFOUT GSPN ƌSFBMƍ
DPEF UIFZ BSF TJNQMJƶFE JO PSEFS UP CF EJTDSFUF FYFSDJTFT 5IBU
XJMM BMMPX VT UP IJHIMJHIU BOE QSBDUJDF TPNF PG UIF UZQF NB
OJQVMBUJPO GSPN 5SBWFSTBCMF BOE 3FBEFS CPUI PG XIJDI BSF
USJDLZ
5IF ƶSTU TJNQMJƶFE QBSU JT UIBU XFƊSF HPJOH UP TFU VQ TPNF
UPZ EBUB JO UIF SFBM QSPHSBNT UIFTF BSF UBLFO GSPN UIF EBUB
JT DPNJOH GSPN TPNFXIFSF FMTF ƈ B EBUBCBTF GPS FYBNQMF
8F KVTU OFFE TPNF MJTUT PG OVNCFST 8FƊSF HPJOH UP VTF TPNF
GVODUJPOT GSPN $POUSPM"QQMJDBUJWF BOE %BUB.BZCF TP XFƊMM
JNQPSU UIPTF BU UIF UPQ PG PVS QSBDUJDF ƶMF 8FƊMM DBMM PVS MJTUT
PG UPZ EBUB CZ DPNNPO WBSJBCMF OBNFT GPS TJNQMJDJUZ
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

module ReaderPractice where

import Control.Applicative
import Data.Maybe

x = [1, 2, 3]
y = [4, 5, 6]
z = [7, 8, 9]

5IF OFYU UIJOH XF XBOU UP EP JT XSJUF TPNF GVODUJPOT UIBU


[JQ UIPTF MJTUT UPHFUIFS BOE VTFT lookup UP ƶOE UIF WBMVF BTTPDJ
BUFE XJUI B TQFDJƶFE LFZ JO PVS [JQQFE MJTUT 'PS EFNPOTUSBUJPO
QVSQPTFT JUƊT OJDF UP IBWF UIF PVUQVUT CF QSFEJDUBCMF TP XF
SFDPNNFOE XSJUJOH TPNF UIBU BSF DPODSFUF WBMVFT BT XFMM BT
POF UIBU DBO CF BQQMJFE UP B WBSJBCMF

lookup :: Eq a => a -> [(a, b)] -> Maybe b

-- zip x and y using 3 as the lookup key


xs :: Maybe Integer
xs = undefined

-- zip y and z using 6 as the lookup key


ys :: Maybe Integer
ys = undefined
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

-- it's also nice to have one that


-- will return Nothing, like this one
-- zip x and y using 4 as the lookup key
zs :: Maybe Integer
zs = lookup 4 $ zip x y

-- now zip x and z using a variable lookup key


z' :: Integer -> Maybe Integer
z' n = undefined

/PX XF XBOU UP BEE UIF BCJMJUZ UP NBLF B Maybe (,) PG WBMVFT


VTJOH "QQMJDBUJWF )BWF x1 NBLF B UVQMF PG xs BOE ys BOE x2
NBLF B UVQMF PG PG ys BOE zs "MTP XSJUF x3 XIJDI UBLFT POF
JOQVU BOE NBLFT B UVQMF PG UIF SFTVMUT PG UXP BQQMJDBUJPOT PG
z' GSPN BCPWF

x1 :: Maybe (Integer, Integer)


x1 = undefined

x2 :: Maybe (Integer, Integer)


x2 = undefined

x3 :: Integer -> (Maybe Integer, Maybe Integer)


x3 = undefined

:PVS PVUQVUT GSPN UIPTF TIPVME MPPL MJLF UIJT


$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

*ReaderPractice> x1
Just (6,9)
*ReaderPractice> x2
Nothing
*ReaderPractice> x3 3
(Just 9,Just 9)

/FYU XFƊSF HPJOH UP NBLF TPNF IFMQFS GVODUJPOT -FUƊT VTF


uncurry UP BMMPX VT UP BEE UIF UXP WBMVFT UIBU BSF JOTJEF B UVQMF

uncurry :: (a -> b -> c) -> (a, b) -> c


-- that first argument is a function
-- in this case, we want it to be addition
-- summed is just uncurry with addition as
-- the first argument

summed :: Num c => (c, c) -> c


summed = undefined

"OE OPX XFƊMM NBLF B GVODUJPO TJNJMBS UP TPNF XFƊWF TFFO


CFGPSF UIBU MJǒT B CPPMFBO GVODUJPO PWFS UXP QBSUJBMMZBQQMJFE
GVODUJPOT

bolt :: Integer -> Bool


-- use &&, >3, <8
bolt = undefined
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

'JOBMMZ XFƊMM CF VTJOH fromMaybe JO UIF main FYFSDJTF TP MFUƊT


MPPL BU UIBU

fromMaybe :: a -> Maybe a -> a

:PV HJWF JU B EFGBVMU WBMVF BOE B .BZCF WBMVF *G UIF .BZCF


WBMVF JT B Just a JU XJMM SFUVSO UIF Ԑ WBMVF *G UIF .BZCF WBMVF
JT B /PUIJOH JU SFUVSOT UIF EFGBVMU WBMVF JOTUFBE

*ReaderPractice> fromMaybe 0 xs
6
*ReaderPractice> fromMaybe 0 zs
0

/PX XFƊMM DPCCMF UPHFUIFS B main GVODUJPO TP UIBU JO POF


GVODUJPO DBMM XF DBO FYFDVUF TFWFSBM UIJOHT BU PODF

main :: IO ()
main = do
print $ sequenceA [Just 3, Just 2, Just 1]
print $ sequenceA [x, y]
print $ sequenceA [xs, ys]
print $ summed <$> ((,) <$> xs <*> ys)
print $ fmap summed ((,) <$> xs <*> zs)
print $ bolt 7
print $ fmap bolt z
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

8IFO ZPV SVO UIJT JO ()$J ZPVS SFTVMUT TIPVME MPPL MJLF
UIJT

*ReaderPractice> main
Just [3,2,1]
[[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]]
Just [6,9]
Just 15
Nothing
True
[True,False,False]

/FYU XFƊSF HPJOH UP BEE POF UIBU DPNCJOFT sequenceA BOE


3FBEFS JO B TPNFXIBU TVSQSJTJOH XBZ BEE UIJT UP ZPVS main
GVODUJPO


print $ sequenceA [(>3), (<8), even] 7

5IF UZQF PG sequenceA JT

sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)


-- so in this:
sequenceA [(>3), (<8), even] 7
-- f ~ (->) a and t ~ []

8F IBWF B 3FBEFS GPS UIF "QQMJDBUJWF GVODUJPOT


BOE B
USBWFSTBCMF GPS UIF MJTU 1SFUUZ IBOEZ 8FƊSF HPJOH UP DBMM UIBU
GVODUJPO sequA GPS UIF QVSQPTFT PG UIF GPMMPXJOH FYFSDJTFT
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

sequA :: Integral a => a -> [Bool]


sequA m = sequenceA [(>3), (<8), even] m

"OE IFODFGPSUI MFU

summed <$> ((,) <$> xs <*> ys)

CF LOPXO BT s'
0, ZPVS UVSO 8JUIJO UIF main GVODUJPO BCPWF XSJUF UIF
GPMMPXJOH ZPV DBO EFMFUF FWFSZUIJOH BǒFS do OPX JG ZPV QSFGFS
ƈ KVTU SFNFNCFS UP VTF print UP CF BCMF UP QSJOU UIF SFTVMUT PG
XIBU ZPVƊSF BEEJOH


 GPME UIF CPPMFBO DPOKVODUJPO PQFSBUPS PWFS UIF MJTU PG


SFTVMUT PG sequA BQQMJFE UP TPNF WBMVF


 BQQMZ sequA UP s' ZPVƊMM OFFE fromMaybe

 BQQMZ bolt UP ys ZPVƊMM OFFE fromMaybe

3FXSJUJOH 4IBXUZ
3FNFNCFS UIF 63- TIPSUFOFS *OTUFBE PG NBOVBMMZ QBTT
JOH UIF EBUBCBTF DPOOFDUJPO rConn GSPN UIF NBJO GVODUJPO
UP UIF BQQ GVODUJPO UIBU HFOFSBUFT B 4DPUUZ BQQ VTF 3FBE
FS5 UP NBLF UIF EBUBCBTF DPOOFDUJPO BWBJMBCMF 8F LOPX ZPV
IBWFOƊU TFFO UIF USBOTGPSNFS WBSJBOU ZFU BOE XFƊMM FYQMBJO UIFN
TPPO CVU ZPV TIPVME USZ UP EP UIF USBOTGPSNBUJPO NFDIBOJ
DBMMZ 3FTFBSDI BT OFDFTTBSZ VTJOH B TFBSDI FOHJOF 6TF UIJT
$)"15&3  '6/$5*0/4 8"*5*/( '03 */165 

WFSTJPO PG UIF BQQ https://github.com/bitemyapp/shawty-prime/


blob/master/app/Main.hs

 'PMMPXVQ SFTPVSDFT


 3FBEFS .POBE "MM "CPVU .POBET
https://wiki.haskell.org/All_About_Monads

 3FBEFS .POBE 1SPHSBNNJOH XJUI .POBET 3FBM 8PSME


)BTLFMM
$IBQUFS 

4UBUF

'PVS DFOUVSJFT BHP


%FTDBSUFT QPOEFSFE UIF
NJOECPEZ QSPCMFN
IPX DBO JODPSQPSFBM
NJOET JOUFSBDU XJUI
QIZTJDBM CPEJFT 5PEBZ
DPNQVUJOH TDJFOUJTUT GBDF
UIFJS PXO WFSTJPO PG UIF
NJOECPEZ QSPCMFN
IPX DBO WJSUVBM TPǒXBSF
JOUFSBDU XJUI UIF SFBM
XPSME

1IJMJQ 8BEMFS


$)"15&3  45"5& 

 4UBUF
8IBU JG * OFFE TUBUF *O )BTLFMM XF IBWF NBOZ NFBOT PG SFQSF
TFOUJOH BDDFTTJOH BOE NPEJGZJOH TUBUF 8F DBO UIJOL PG TUBUF
BT EBUB UIBU FYJTUT JO BEEJUJPO UP UIF JOQVUT BOE PVUQVUT PG PVS
GVODUJPOT EBUB UIBU DBO QPUFOUJBMMZ DIBOHF BǒFS FBDI GVODUJPO
JT FWBMVBUFE
*O UIJT DIBQUFS XF XJMM

Ƒ UBML BCPVU XIBU TUBUF NFBOT

Ƒ FYQMPSF TPNF XBZT PG IBOEMJOH TUBUF JO )BTLFMM

Ƒ HFOFSBUF TPNF NPSF SBOEPN OVNCFST

Ƒ BOE FYBNJOF UIF 4UBUF OFXUZQF BOE .POBE JOTUBODF

 8IBU JT TUBUF


5IF DPODFQU PG TUBUF PSJHJOBUFT JO UIF DJSDVJU BOE BVUPNBUB
UIFPSZ UIBU NVDI PG DPNQVUFS TDJFODF BOE QSPHSBNNJOH CF
HBO XJUI 5IF TJNQMFTU GPSN PG TUBUF DPVME CF VOEFSTUPPE BT B
MJHIU TXJUDI " MJHIU TXJUDI IBT UXP QPTTJCMF TUBUFT PO PS PƵ
5IBU EJTQPTJUJPO PG UIF MJHIU TXJUDI CFJOH PO PS PƵ DPVME CF
VOEFSTUPPE BT JUT ƌTUBUFƍ 4JNJMBSMZ USBOTJTUPST JO DPNQVUFST
IBWF CJOBSZ TUBUFT PG CFJOH PO PS PƵ 5IJT JT B WFSZ MPXMFWFM
XBZ PG TFFJOH JU CVU UIJT NBQT POUP UIF ƌTUBUFƍ UIBU FYJTUT JO
DPNQVUFS NFNPSZ
$)"15&3  45"5& 

*O NPTU JNQFSBUJWF QSPHSBNNJOH MBOHVBHFT UIJT TUBUFGVM


OFTT JT QFSWBTJWF JNQMJDJU BOE OPU SFGFSFODFE JO UIF UZQFT
PG ZPVS GVODUJPOT *O )BTLFMM XFƊSF OPU BMMPXFE UP TFDSFUMZ
DIBOHF TPNF WBMVF BMM XF DBO EP JT BDDFQU BSHVNFOUT BOE
SFUVSO B SFTVMU 5IF 4UBUF UZQF JO )BTLFMM JT B NFBOT PG FYQSFTT
JOH ƌTUBUFƍ XIJDI NBZ DIBOHF JO UIF DPVSTF PG FWBMVBUJOH DPEF
XJUIPVU SFTPSU UP NVUBUJPO 5IF NPOBEJD JOUFSGBDF GPS 4UBUF
JT NVDI BT ZPVƊWF TFFO BMSFBEZ NPSF PG B DPOWFOJFODF UIBO B
TUSJDU OFDFTTJUZ GPS XPSLJOH XJUI 4UBUF
8F IBWF UIF PQUJPO UP DBQUVSF UIF JEFB BOE DPOWFOJFODF
PG B WBMVF XIJDI QPUFOUJBMMZ DIBOHFT XJUI FBDI DPNQVUBUJPO
XJUIPVU SFTPSUJOH UP NVUBCJMJUZ 4UBUF DBQUVSFT UIJT JEFB BOE
DMFBOT VQ UIF CPPLLFFQJOH SFRVJSFE *G ZPV OFFE JOQMBDF
NVUBUJPO UIFO UIF ST UZQF JT XIBU ZPV XBOU CVU XF XJMM OPU
CF DPWFSJOH JU JO UIJT CPPL
*O )BTLFMM JG XF VTF UIF 4UBUF UZQF BOE JUT BTTPDJBUFE .POBE
GPS DPOWFOJFODF OPU TUSJDUMZ OFDFTTBSZ
XF DBO IBWF TUBUF
XIJDI

 EPFTOƊU SFRVJSF *0

 JT MJNJUFE POMZ UP UIF EBUB JO PVS 4UBUF DPOUBJOFS

 NBJOUBJOT SFGFSFOUJBM USBOTQBSFODZ

 JT FYQMJDJU JO UIF UZQFT PG PVS GVODUJPOT


$)"15&3  45"5& 

5IFSF BSF PUIFS NFBOT PG TIBSJOH EBUB XJUIJO B QSPHSBN


XIJDI BSF EFTJHOFE GPS EJƵFSFOU OFFET UIBO UIF 4UBUF EBUBUZQF
JUTFMG 4UBUF JT BQQSPQSJBUF XIFO ZPV XBOU UP FYQSFTT ZPVS
QSPHSBN JO UFSNT PG WBMVFT UIBU QPUFOUJBMMZ WBSZ XJUI FBDI
FWBMVBUJPO TUFQ XIJDI DBO CF SFBE BOE NPEJƶFE CVU EPOƊU
PUIFSXJTF IBWF TQFDJƶD PQFSBUJPOBM DPOTUSBJOUT

 3BOEPN OVNCFST


"T XF EJE JO UIF QSFWJPVT DIBQUFS XFƊMM TUBSU XJUI BO FYUFOEFE
FYBNQMF 5IJT XJMM IFMQ ZPV HFU BO JEFB PG UIF QSPCMFN XFƊSF
USZJOH UP TPMWF XJUI UIF 4UBUF EBUBUZQF
8FƊMM CF VTJOH UIF SBOEPN MJCSBSZ WFSTJPO  JO UIJT FY
BNQMF
'JSTU MFUƊT HJWF BO PWFSWJFX PG TPNF PG UIF GVODUJPOT XFƊMM CF
VTJOH IFSF 8F VTFE UIF 4ZTUFN3BOEPN MJCSBSZ CBDL JO UIF
DIBQUFS XIFSF XF CVJMU UIF IBOHNBO HBNF CVU XFƊMM CF VTJOH
TPNF EJƵFSFOU GVODUJPOT GPS UIJT FYBNQMF 5IJT JT JO CSPBE
TUSPLFT JU JTOƊU NFBOU UP HP JOUP HSFBU EFUBJM BCPVU IPX UIFTF
HFOFSBUPST XPSL
4ZTUFN3BOEPN JT EFTJHOFE UP HFOFSBUF QTFVEPSBOEPN
WBMVFT :PV DBO HFOFSBUF UIPTF WBMVFT UISPVHI QSPWJEJOH B
TFFE WBMVF PS CZ VTJOH UIF TZTUFNJOJUJBMJTFE HFOFSBUPS 8FƊMM
CF VTJOH UIF GPMMPXJOH GSPN UIBU MJCSBSZ

https://hackage.haskell.org/package/random
$)"15&3  45"5& 

 0OF PG UIF UZQFT XFƊMM CF TFFJOH IFSF StdGen JT B EBUBUZQF


UIBU JT B QSPEVDU PG UXP Int32 WBMVFT 4P B WBMVF PG UZQF
4UE(FO BMXBZT DPNQSJTFT UXP *OU WBMVFT 5IFZ BSF UIF
TFFE WBMVFT VTFE UP HFOFSBUF UIF OFYU SBOEPN OVNCFS

 mkStdGen IBT UIF UZQF

mkStdGen :: Int -> StdGen

8FƊMM JHOPSF UIF JNQMFNFOUBUJPO BU UIJT QPJOU CFDBVTF


UIPTF EFUBJMT BSFOƊU JNQPSUBOU IFSF 5IF JEFB JT UIBU JU
UBLFT BO *OU BSHVNFOU BOE NBQT JU JOUP B HFOFSBUPS UP
SFUVSO B WBMVF PG UZQF 4UE(FO XIJDI JT B QBJS PG *OU
WBMVFT

 next IBT UIF UZQF

next :: g -> (Int, g)

XIFSF Ԗ JT B WBMVF PG UZQF 4UE(FO 5IF *OU UIBU JT ƶSTU JO


UIF UVQMF JT UIF QTFVEPSBOEPN OVNCFS HFOFSBUFE GSPN
UIF 4UE(FO WBMVF UIF TFDPOE WBMVF JT B OFX 4UE(FO WBMVF

 random IBT UIF UZQF

random :: (RandomGen g, Random a) => g -> (a, g)

5IJT JT TJNJMBS UP next CVU BMMPXT VT UP HFOFSBUF SBOEPN


WBMVFT UIBU BSFOƊU OVNCFST 5IF SBOHF HFOFSBUFE XJMM CF
EFUFSNJOFE CZ UIF UZQF
$)"15&3  45"5& 

/PX MFUƊT IBWF B MJUUMF EFNPOTUSBUJPO PG UIFTF

Prelude> import System.Random


Prelude> mkStdGen 0
1 1
Prelude> :t mkStdGen 0
mkStdGen 0 :: StdGen
Prelude> let sg = mkStdGen 0
Prelude> :t next sg
next sg :: (Int, StdGen)
Prelude> next sg
(2147482884,40014 40692)
Prelude> next sg
(2147482884,40014 40692)

8F HFU UIF TBNF BOTXFS UXJDF CFDBVTF UIF VOEFSMZJOH GVOD


UJPO UIBUƊT EFDJEJOH UIF WBMVFT SFUVSOFE JT QVSF UIF UZQF EPFTOƊU
QFSNJU UIF QFSGPSNBODF PG BOZ FƵFDUT UP HFU TQPPLZ BDUJPO
%FƶOF B OFX WFSTJPO PG sg UIBU QSPWJEFT B EJƵFSFOU JOQVU WBMVF
UP mkStdGen BOE TFF XIBU IBQQFOT
4P XF IBWF B WBMVF DBMMFE next sg /PX JG XF XBOU UP VTF
UIBU UP HFOFSBUF UIF OFYU SBOEPN OVNCFS XF OFFE UP GFFE UIF
4UE(FO WBMVF GSPN UIBU UVQMF UP next BHBJO 8F DBO VTF snd UP
FYUSBDU UIBU 4UE(FO WBMVF BOE QBTT JU BT BO JOQVU UP next

Prelude> snd (next sg)


40014 40692
$)"15&3  45"5& 

Prelude> let newSg = snd (next sg)


Prelude> :t newSg
newSg :: StdGen
Prelude> next newSg
(2092764894,1601120196 1655838864)

:PVƊMM LFFQ HFUUJOH UIF TBNF SFTVMUT PG next UIFSF CVU ZPV
DBO FYUSBDU UIBU 4UE(FO WBMVF BOE QBTT JU UP next BHBJO UP HFU B
OFX UVQMF

Prelude> next (snd (next newSg))


(1679949200,1635875901 2103410263)

/PX XFƊMM MPPL BU B GFX FYBNQMFT VTJOH random #FDBVTF


random DBO HFOFSBUF WBMVFT PG EJƵFSFOU UZQFT XF OFFE UP TQFDJGZ
UIF UZQF UP VTF

Prelude> :t random newSg


random newSg :: Random a => (a, StdGen)
Prelude> random newSg :: (Int, StdGen)
(138890298504988632,439883729 1872071452)
Prelude> random newSg :: (Double, StdGen)
(0.41992072972993366,439883729 1872071452)

4JNQMF FOPVHI CVU XIBU JG XF XBOU B OVNCFS XJUIJO B


SBOHF
$)"15&3  45"5& 

Prelude> :t randomR
randomR :: (RandomGen g, Random a) => (a, a) -> g -> (a, g)
Prelude> randomR (0, 3) newSg :: (Int, StdGen)
(1,1601120196 1655838864)
Prelude> randomR (0, 3) newSg :: (Double, StdGen)
(1.259762189189801,439883729 1872071452)

8F IBWF UP QBTT UIF OFX TUBUF PG UIF SBOEPN OVNCFS HFO


FSBUPS UP UIF next GVODUJPO UP HFU B OFX WBMVF

Prelude> let rx :: (Int, StdGen); rx = random (snd sg3)


Prelude> rx
(2387576047905147892,1038587761 535353314)
Prelude> snd rx
1038587761 535353314

5IJT DIBJOJOH PG TUBUF DBO HFU UFEJPVT "EESFTTJOH UIJT UF


EJVN JT PVS BJN JO UIJT DIBQUFS

 5IF 4UBUF OFXUZQF


4UBUF JT EFƶOFE JO B OFXUZQF MJLF 3FBEFS JO UIF QSFWJPVT DIBQ
UFS BOE UIBU UZQF MPPLT MJLF UIJT

newtype State s a =
State { runState :: s -> (a, s) }
$)"15&3  45"5& 

*UƊT JOJUJBMMZ B CJU TUSBOHF MPPLJOH CVU ZPV NJHIU OPUJDF TPNF
TJNJMBSJUZ UP UIF 3FBEFS OFXUZQF

newtype Reader r a =
Reader { runReader :: r -> a }

"DUVBMMZ XFƊWF TFFO TFWFSBM OFXUZQFT XIPTF DPOUFOUT BSF B


GVODUJPO QBSUJDVMBSMZ XJUI PVS .POPJE OFXUZQFT 4VN 1SPE
VDU FUD
 /FXUZQFT NVTU IBWF UIF TBNF VOEFSMZJOH SFQSFTFOUB
UJPO BT UIF UZQF UIFZ XSBQ BT UIF OFXUZQF XSBQQFS EJTBQQFBST
BU DPNQJMF UJNF 4P UIF GVODUJPO DPOUBJOFE JO UIF OFXUZQF
NVTU CF JTPNPSQIJD UP UIF UZQF JU XSBQT 5IBU JT UIFSF NVTU
CF B XBZ UP HP GSPN UIF OFXUZQF UP UIF UIJOH JU XSBQT BOE CBDL
BHBJO XJUIPVU MPTJOH JOGPSNBUJPO 'PS FYBNQMF UIF GPMMPXJOH
EFNPOTUSBUFT BO JTPNPSQIJTN

type Iso a b = (a -> b, b -> a)

newtype Sum a = Sum { getSum :: a }

sumIsIsomorphicWithItsContents :: Iso a (Sum a)


sumIsIsomorphicWithItsContents =
(Sum, getSum)

8IFSFBT UIF GPMMPXJOH EP OPU


$)"15&3  45"5& 

-- Not an isomorphism, because it might not work.


(a -> Maybe b, b -> Maybe a)

-- Not an isomorphism for two reasons. You lose information


-- whenever there was more than one element in [a]. Also,
-- [a] -> a is partial because there might not be any
-- elements.
[a] -> a, a -> [a]

8JUI UIBU JO NJOE MFU VT MPPL BU UIF 4UBUF EBUB DPOTUSVDUPS


BOE SVO4UBUF SFDPSE BDDFTTPS BT PVS NFBOT PG QVUUJOH B WBMVF
JO BOE UBLJOH B WBMVF PG PVU UIF 4UBUF UZQF

State :: (s -> (a, s)) -> State s a

runState :: State s a -> s -> (a, s)

4UBUF JT B GVODUJPO UIBU UBLFT JOQVU TUBUF BOE SFUVSOT BO


PVUQVU WBMVF Ԑ UVQMFE XJUI UIF OFX TUBUF WBMVF 5IF LFZ JT
UIBU UIF QSFWJPVT TUBUF WBMVF GSPN FBDI BQQMJDBUJPO JT DIBJOFE
UP UIF OFYU POF BOE UIJT JT OPU BO VODPNNPO QBUUFSO 4UBUF JT
PǒFO VTFE GPS UIJOHT MJLF SBOEPN OVNCFS HFOFSBUPST TPMWFST
HBNFT BOE DBSSZJOH XPSLJOH NFNPSZ XIJMF USBWFSTJOH B EBUB
TUSVDUVSF 5IF QPMZNPSQIJTN NFBOT ZPV EPOƊU IBWF UP NBLF
B OFX TUBUF GPS FBDI QPTTJCMF JOTUBOUJBUJPO PG Ԣ BOE Ԑ
-FUƊT HFU CBDL UP PVS SBOEPN OVNCFST
$)"15&3  45"5& 

/PUF UIBU random TIPVME MPPL BO BXGVM MPU MJLF 4UBUF UP ZPV
IFSF

random :: (Random a) => StdGen -> (a, StdGen)


State { runState :: s -> (a, s) }

*G XF MPPL BU UIF UZQF PG randomR PODF QBSUJBMMZ BQQMJFE JU


TIPVME BMTP SFNJOE ZPV PG 4UBUF

randomR :: (...) => (a, a) -> g -> (a, g)


State { runState :: s -> (a, s) }

 5ISPX EPXO


/PX MFU VT VTF UIJT LJU UP HFOFSBUF EJF TVDI BT GPS B HBNF
$)"15&3  45"5& 

module RandomExample where

import System.Random

-- Six-sided die
data Die =
DieOne
| DieTwo
| DieThree
| DieFour
| DieFive
| DieSix
deriving (Eq, Show)

"T ZPV NJHIU FYQFDU XFƊMM CF VTJOH UIF random MJCSBSZ BOE B
TJNQMF Die EBUBUZQF UP SFQSFTFOU B TJYTJEFE EJF
$)"15&3  45"5& 

intToDie :: Int -> Die


intToDie n =
case n of
1 -> DieOne
2 -> DieTwo
3 -> DieThree
4 -> DieFour
5 -> DieFive
6 -> DieSix
-- Use this tactic _extremely_ sparingly.
x -> error $ "intToDie got non 1-6 integer: " ++ show x

%POƊU VTF ƉFSSPSƊ PVUTJEF PG FYQFSJNFOUT MJLF UIJT PS JO DBTFT


XIFSF UIF CSBODI ZPVƊSF JHOPSJOH JT QSPWBCMZ JNQPTTJCMF 8F
EP OPU VTF UIF XPSE QSPWBCMZ IFSF MJHIUMZ
/PX XF OFFE UP SPMM UIF EJDF

#FDBVTF QBSUJBM GVODUJPOT BSF B QBJO ZPV TIPVME POMZ VTF BO FSSPS MJLF UIJT XIFO
UIF CSBODI UIBU XPVME TQBXO UIF FSSPS DBO MJUFSBMMZ OFWFS IBQQFO 6OFYQFDUFE TPǒXBSF
GBJMVSFT BSF PǒFO EVF UP UIJOHT MJLF UIJT *U JT BMTP DPNQMFUFMZ VOOFDFTTBSZ JO )BTLFMM XF
IBWF HPPE BMUFSOBUJWFT MJLF VTJOH .BZCF PS &JUIFS 5IF POMZ SFBTPO XF EJEOƊU IFSF JT UP
LFFQ JU TJNQMF BOE GPDVT BUUFOUJPO PO UIF 4UBUF .POBE
$)"15&3  45"5& 

rollDieThreeTimes :: (Die, Die, Die)


rollDieThreeTimes = do
-- this will produce the same results every
-- time because it is free of effects.
-- This is fine for this demonstration.
let s = mkStdGen 0
(d1, s1) = randomR (1, 6) s
(d2, s2) = randomR (1, 6) s1
(d3, _) = randomR (1, 6) s2
(intToDie d1, intToDie d2, intToDie d3)

5IJT DPEF JTOƊU PQUJNBM CVU JU EPFT XPSL *U XJMM QSPEVDF


UIF TBNF SFTVMUT FWFSZ UJNF CFDBVTF JU JT GSFF PG FƵFDUT CVU
ZPV DBO NBLF JU QSPEVDF B OFX SFTVMU PO B OFX EJDF SPMM JG ZPV
NPEJGZ UIF TUBSU WBMVF 5SZ JU B DPVQMF PG UJNFT UP TFF XIBU XF
NFBO *U TFFNT VOMJLFMZ UIBU UIJT XJMM EFWFMPQ JOUP B HBNCMJOH
BEEJDUJPO CVU JO UIF FWFOU JU EPFT UIF BVUIPST EJTDMBJN MJBCJMJUZ
GPS TVDI
4P IPX DBO XF JNQSPWF PVS TVCPQUJNBM DPEF UIFSF 8JUI
4UBUF PG DPVSTF
$)"15&3  45"5& 

module RandomExample2 where

import Control.Applicative (liftA3)


import Control.Monad (replicateM)
import Control.Monad.Trans.State
import System.Random

'JSTU XFƊMM BEE TPNF OFX JNQPSUT :PVƊMM OFFE transformers


UP CF JOTUBMMFE GPS UIF 4UBUF JNQPSU UP XPSL CVU UIBU TIPVME
IBWF DPNF XJUI ZPVS ()$ JOTUBMM TP ZPV TIPVME CF HPPE UP
HP
6TJOH 4UBUF XJMM BMMPX VT UP GBDUPS PVU UIF HFOFSBUJPO PG B
TJOHMF %JF

rollDie :: State StdGen Die


rollDie = state $ do
(n, s) <- randomR (1, 6)
return (intToDie n, s)

'PS PVS QVSQPTFT UIF state GVODUJPO JT B DPOTUSVDUPS UIBU


UBLFT B 4UBUFMJLF GVODUJPO BOE FNCFET JU JO UIF 4UBUF NPOBE
USBOTGPSNFS *HOPSF UIF USBOTGPSNFS QBSU GPS OPX ƈ XFƊMM HFU
UIFSF 5IF TUBUF GVODUJPO IBT UIF GPMMPXJOH UZQF

state :: Monad m => (s -> (a, s)) -> StateT s m a

/PUF UIBU XFƊSF CJOEJOH UIF SFTVMU PG randomR PVU PG UIF 4UBUF
NPOBE UIF do CMPDL JT JO SBUIFS UIBO VTJOH let 5IJT JT TUJMM NPSF
$)"15&3  45"5& 

WFSCPTF UIBO JT OFDFTTBSZ 8F DBO MJǒ PVS intToDie GVODUJPO


PWFS UIF 4UBUF

rollDie' :: State StdGen Die


rollDie' =
intToDie <$> state (randomR (1, 6))

State StdGen IBE B ƶOBM UZQF BSHVNFOU PG *OU 8F MJǒFE Int


-> Die PWFS JU BOE USBOTGPSNFE UIBU ƶOBM UZQF BSHVNFOU UP %JF
8FƊMM FYFSDJTF NPSF CSFWJUZ VQGSPOU JO UIF OFYU GVODUJPO

rollDieThreeTimes' :: State StdGen (Die, Die, Die)


rollDieThreeTimes' =
liftA3 (,,) rollDie rollDie rollDie

-JǒJOH UIF UISFFUVQMF DPOTUSVDUPS PWFS UISFF 4UBUF BDUJPOT


UIBU QSPEVDF %JF WBMVFT XIFO HJWFO BO JOJUJBM TUBUF UP XPSL
XJUI )PX EPFT UIJT MPPL JO QSBDUJDF

Prelude> evalState rollDieThreeTimes' (mkStdGen 0)


(DieSix,DieSix,DieFour)
Prelude> evalState rollDieThreeTimes' (mkStdGen 1)
(DieSix,DieFive,DieTwo)

4FFNT UP XPSL ƶOF "HBJO UIF TBNF JOQVUT HJWF VT UIF TBNF
SFTVMU 8IBU JG XF XBOU B MJTU PG %JF JOTUFBE PG B UVQMF
$)"15&3  45"5& 

-- Seems appropriate?
repeat :: a -> [a]

infiniteDie :: State StdGen [Die]


infiniteDie = repeat <$> rollDie

%PFT UIJT infiniteDie GVODUJPO EP XIBU XF XBOU PS FYQFDU


8IBU JT JU SFQFBUJOH

Prelude> take 6 $ evalState infiniteDie (mkStdGen 0)


[DieSix,DieSix,DieSix,DieSix,DieSix,DieSix]

8F BMSFBEZ LOPX CBTFE PO QSFWJPVT JOQVUT UIBU UIF ƶSTU 


WBMVFT TIPVMEOƊU CF JEFOUJDBM GPS B TFFE WBMVF PG  4P XIBU
IBQQFOFE 8IBU IBQQFOFE JT XF SFQFBUFE B TJOHMF EJF WBMVF
ƈ XF EJEOƊU SFQFBU UIF TUBUF BDUJPO UIBU QSPEVDFT B EJF 5IJT JT
XIBU XF OFFE

replicateM :: Monad m => Int -> m a -> m [a]

nDie :: Int -> State StdGen [Die]


nDie n = replicateM n rollDie

"OE XIFO XF VTF JU

Prelude> evalState (nDie 5) (mkStdGen 0)


[DieSix,DieSix,DieFour,DieOne,DieFive]
$)"15&3  45"5& 

Prelude> evalState (nDie 5) (mkStdGen 1)


[DieSix,DieFive,DieTwo,DieSix,DieFive]

8F HFU QSFDJTFMZ XIBU XF XBOUFE

,FFQ PO SPMMJOH
*O UIF GPMMPXJOH FYBNQMF XF LFFQ SPMMJOH B TJOHMF EJF VOUJM XF
SFBDI PS FYDFFE B TVN PG 

rollsToGetTwenty :: StdGen -> Int


rollsToGetTwenty g = go 0 0 g
where go :: Int -> Int -> StdGen -> Int
go sum count gen
| sum >= 20 = count
| otherwise =
let (die, nextGen) = randomR (1, 6) gen
in go (sum + die) (count + 1) nextGen

5IFO TFFJOH JU JO BDUJPO

Prelude> rollsToGetTwenty (mkStdGen 0)


5
Prelude> rollsToGetTwenty (mkStdGen 0)
5
$)"15&3  45"5& 

8F DBO BMTP VTF randomIO XIJDI VTFT *0 UP HFU B OFX WBMVF


FBDI UJNF XJUIPVU OFFEJOH UP DSFBUF B VOJRVF WBMVF GPS UIF
4UE(FO

Prelude> :t randomIO
randomIO :: Random a => IO a
Prelude> (rollsToGetTwenty . mkStdGen) <$> randomIO
6
Prelude> (rollsToGetTwenty . mkStdGen) <$> randomIO
7

6OEFS UIF IPPE JUƊT UIF TBNF JOUFSGBDF BOE 4UBUF .POBE
ESJWFO NFDIBOJTN CVU JUƊT NVUBUJOH B TJOHMF HMPCBMMZ VTFE
4UE(FO UP XBML UIF HFOFSBUPS GPSXBSE PO FBDI VTF 4FF UIF
random MJCSBSZ TPVSDF DPEF UP TFF IPX UIJT XPSLT

&YFSDJTFT 3PMM :PVS 0XO

 3FGBDUPS rollsToGetTwenty JOUP IBWJOH UIF MJNJU CF B GVOD


UJPO BSHVNFOU

rollsToGetN :: Int -> StdGen -> Int


rollsToGetN = undefined

 $IBOHF rollsToGetN UP SFDPSEJOH UIF TFSJFT PG EJF UIBU PD


DVSSFE JO BEEJUJPO UP UIF DPVOU

rollsCountLogged :: Int -> StdGen -> (Int, [Die])


rollsCountLogged = undefined
$)"15&3  45"5& 

 8SJUF 4UBUF GPS ZPVSTFMG


6TF UIF EBUBUZQF EFƶOJUJPO GSPN UIF CFHJOOJOH PG UIJT DIBQUFS
XJUI UIF OBNF DIBOHFE UP BWPJE DPOƷJDUT JO DBTF ZPV IBWF
4UBUF JNQPSUFE GSPN UIF MJCSBSJFT transformers PS mtl 8FƊSF
DBMMJOH JU Moi CFDBVTF XF FOKPZ BMMVTJPOT UP GBNPVT RVPUBUJPOT 
GFFM GSFF UP DIBOHF UIF OBNF JG ZPV XJTI UP QSPUFTU BCTPMVUF
NPOBSDIZ KVTU DIBOHF UIFN DPOTJTUFOUMZ UISPVHIPVU

newtype Moi s a =
Moi { runMoi :: s -> (a, s) }

4UBUF 'VODUPS
*NQMFNFOU UIF 'VODUPS JOTUBODF GPS 4UBUF

instance Functor (Moi s) where


fmap :: (a -> b) -> Moi s a -> Moi s b
fmap f (Moi g) = ???

Prelude> runMoi ((+1) <$> (Moi $ \s -> (0, s))) 0


(1,0)

4UBUF "QQMJDBUJWF
8SJUF UIF "QQMJDBUJWF JOTUBODF GPS 4UBUF

8F BSF SFGFSSJOH UP UIF QPTTJCMZ BQPDSZQIBM
RVPUBUJPO BUUSJCVUFE UP UIF 'SFODI
,JOH -PVJT 9*7 ƌ-Ɗ&UBU DƊFTU NPJƍ 'PS UIPTF PG ZPV XIP EP OPU TQFBL 'SFODI JU NFBOT ƌ*
BN UIF 4UBUFƍ $IFFST
$)"15&3  45"5& 

instance Applicative (Moi s) where


pure :: a -> Moi s a
pure a = ???

(<*>) :: Moi s (a -> b)


-> Moi s a
-> Moi s b
(Moi f) <*> (Moi g) =
???

4UBUF .POBE
8SJUF UIF .POBE JOTUBODF GPS 4UBUF

instance Monad (Moi s) where


return = pure

(>>=) :: Moi s a
-> (a -> Moi s b)
-> Moi s b
(Moi f) >>= g =
???
$)"15&3  45"5& 

 (FU B DPEJOH KPC XJUI POF XFJSE


USJDL
4PNF DPNQBOJFT XJMM VTF 'J[[#V[[ UP TDSFFO OPU TP NVDI
UFTU
DBOEJEBUFT BQQMZJOH UP TPǒXBSF QPTJUJPOT 5IF QSPCMFN
TUBUFNFOU HPFT

8SJUF B QSPHSBN UIBU QSJOUT UIF OVNCFST GSPN  UP


 #VU GPS NVMUJQMFT PG UISFF QSJOU ƌ'J[[ƍ JOTUFBE PG
UIF OVNCFS BOE GPS UIF NVMUJQMFT PG ƶWF QSJOU ƌ#V[[ƍ
'PS OVNCFST XIJDI BSF NVMUJQMFT PG CPUI UISFF BOE
ƶWF QSJOU ƌ'J[[#V[[ƍ

" UZQJDBM ƶ[[CV[[ TPMVUJPO JO )BTLFMM MPPLT TPNFUIJOH MJLF

fizzBuzz :: Integer -> String


fizzBuzz n | n `mod` 15 == 0 = "FizzBuzz"
| n `mod` 5 == 0 = "Buzz"
| n `mod` 3 == 0 = "Fizz"
| otherwise = show n

main :: IO ()
main =
mapM_ (putStrLn . fizzBuzz) [1..100]

http://c2.com/cgi/wiki?FizzBuzzTest
$)"15&3  45"5& 

:PV XJMM DSBǒ B ƶ[[CV[[ UIBU NBLFT HPVUT PG CMPPE DPNF


PVU PG ZPVS JOUFSWJFXFSƊT FZF TPDLFUT VTJOH 4UBUF 5IJT JT B TVJU
BCMF QVOJTINFOU GPS BTLJOH B TPǒXBSF DBOEJEBUF UP XSJUF UIJT
JO QFSTPO BǒFS QSFTVNBCMZ HFUUJOH UISPVHI B DPVQMF QIPOF
TDSFFOT

import Control.Monad
import Control.Monad.Trans.State

fizzBuzz :: Integer -> String


fizzBuzz n | n `mod` 15 == 0 = "FizzBuzz"
| n `mod` 5 == 0 = "Fizz"
| n `mod` 3 == 0 = "Buzz"
| otherwise = show n

fizzbuzzList :: [Integer] -> [String]


fizzbuzzList list =
execState (mapM_ addResult list) []

addResult :: Integer -> State [String]


addResult n = do
xs <- get
let result = fizzBuzz n
put (result : xs)

/PUF UIBU State JT B UZQF BMJBT PG StateT ZPV JNQPSUFE


$)"15&3  45"5& 

main :: IO ()
main =
mapM_ putStrLn $ reverse $ fizzbuzzList [1..100]

5IF HPPE QBSU IFSF JT UIBU XFƊSF DPMMFDUJOH EBUB JOJUJBMMZ


CFGPSF EVNQJOH UIF SFTVMUT UP TUBOEBSE PVUQVU WJB putStrLn
5IF CBE JT UIBU XFƊSF SFWFSTJOH B MJTU 3FWFSTJOH TJOHMZMJOLFE
MJTUT JT QSFUUZ CBE FWFO JO )BTLFMM BOE XPOƊU UFSNJOBUF PO BO
JOƶOJUF MJTU 0OF PG UIF JTTVFT JT UIBU XFƊSF BDDFQUJOH BO JOQVU
UIBU EFƶOFT UIF OVNCFST XFƊMM VTF ƶ[[CV[[ PO MJOFBSMZ GSPN
CFHJOOJOH UP FOE
5IFSF BSF B DPVQMF XBZT XF DPVME IBOEMF UIJT 0OF JT UP
VTF B EBUB TUSVDUVSF XJUI DIFBQFS BQQFOEJOH UP UIF FOE 6TJOH
(++) SFDVSTJWFMZ DBO CF WFSZ TMPX TP MFUƊT VTF TPNFUIJOH UIBU
DBO BQQFOE JO DPOTUBOU UJNF 5IF DPVOUFSQBSU UP [] XIJDI IBT
UIJT QSPQFSUZ JT UIF EJƵFSFODF MJTU XIJDI IBT 0 
BQQFOE

https://github.com/spl/dlist
$)"15&3  45"5& 

import Control.Monad
import Control.Monad.Trans.State
-- http://hackage.haskell.org/package/dlist
import qualified Data.DList as DL

fizzBuzz :: Integer -> String


fizzBuzz n | n `mod` 15 == 0 = "FizzBuzz"
| n `mod` 5 == 0 = "Fizz"
| n `mod` 3 == 0 = "Buzz"
| otherwise = show n
$)"15&3  45"5& 

fizzbuzzList :: [Integer] -> [String]


fizzbuzzList list =
let dlist = execState (mapM_ addResult list) DL.empty
in DL.apply dlist [] -- convert back to normal list

addResult :: Integer -> State (DL.DList String)


addResult n = do
xs <- get
let result = fizzBuzz n
-- snoc appends to the end, unlike
-- cons which adds to the front
put (DL.snoc xs result)

main :: IO ()
main =
mapM_ putStrLn $ fizzbuzzList [1..100]

8F DBO DMFBO UIJT VQ GVSUIFS *G ZPV IBWF ()$  PS OFXFS


mapM_ XJMM TQFDJGZ B 'PMEBCMF UZQF OPU POMZ B MJTU

Prelude> :t mapM_
mapM_ :: (Monad m, Foldable t) => (a -> m b) -> t a -> m ()

#Z MFUUJOH DListƊT 'PMEBCMF JOTUBODF EP UIF DPOWFSTJPO UP B


MJTU GPS VT XF DBO FMJNJOBUF TPNF DPEF
$)"15&3  45"5& 

fizzbuzzList :: [Integer] -> DL.DList String


fizzbuzzList list =
execState (mapM_ addResult list) DL.empty

addResult :: Integer -> State (DL.DList String)


addResult n = do
xs <- get
let result = fizzBuzz n
put (DL.snoc xs result)

main :: IO ()
main =
mapM_ putStrLn $ fizzbuzzList [1..100]

%-JTUƊT 'PMEBCMF JOTUBODF DPOWFSUT UP B MJTU CFGPSF GPMEJOH


CFDBVTF PG MJNJUBUJPOT TQFDJƶD UP UIF EBUBUZQF :PV HFU DIFBQ
BQQFOEJOH CVU ZPV HJWF VQ UIF BCJMJUZ UP ƌTFFƍ XIBU ZPVƊWF
CVJMU VOMFTT ZPVƊSF XJMMJOH UP EP BMM UIF XPSL PG CVJMEJOH UIF
TUSVDUVSF 8FƊMM EJTDVTT UIJT JO NPSF EFUBJM JO B GPSUIDPNJOH
DIBQUFS
0OF UIJOH UIBU NBZ TUSJLF ZPV IFSF JT UIBU UIF VTF PG 4UBUF
XBT UPUBMMZ TVQFSƷVPVT 5IBUƊT HPPE *UƊT OPU DPNNPO ZPV
SFBMMZ OFFE 4UBUF BT TVDI JO )BTLFMM :PV NJHIU VTF B EJƵFSFOU
GPSN PG 4UBUF DBMMFE ST BT B TFMFDUJWF PQUJNJ[BUJPO CVU 4UBUF
JUTFMG JT B TUZMJTUJD DIPJDF UIBU GBMMT PVU PG XIBU UIF DPEF JT UFMMJOH
ZPV %POƊU GFFM DPNQFMMFE UP VTF PS OPU VTF 4UBUF 1MFBTF
$)"15&3  45"5& 

GSJHIUFO TPNF JOUFSWJFXFST XJUI B TQPPLZ ƶ[[CV[[ .BLF


TPNFUIJOH FWFO XFJSEFS UIBO XIBU XFƊWF TIPXO ZPV IFSF

'J[[CV[[ %JƵFSFOUMZ
*UƊT BO FYFSDJTF 3BUIFS UIBO DIBOHJOH UIF VOEFSMZJOH EBUB
TUSVDUVSF ƶY PVS SFWFSTJOH ƶ[[CV[[ CZ DIBOHJOH UIF DPEF JO
UIF GPMMPXJOH XBZ

fizzbuzzFromTo :: Integer -> Integer -> [String]


fizzbuzzFromTo = undefined

$POUJOVF UP VTF DPOTJOH JO UIF DPOTUSVDUJPO PG UIF SFTVMU


MJTU CVU IBWF JU DPNF PVU JO UIF SJHIU PSEFS UP CFHJO XJUI
CZ FOVNFSBUJOH UIF TFRVFODF CBDLXBSET 5IJT TPSU PG UBDUJD JT
NPSF DPNNPOMZ IPX ZPVƊMM XBOU UP ƶY ZPVS DPEF XIFO ZPVƊSF
RVBTIJOH VOOFDFTTBSZ SFWFSTBMT

 $IBQUFS FYFSDJTFT


8SJUF UIF GPMMPXJOH GVODUJPOT :PVƊMM XBOU UP VTF ZPVS PXO
State UZQF GPS XIJDI ZPVƊWF EFƶOFE UIF 'VODUPS "QQMJDBUJWF
BOE .POBE

 $POTUSVDU B 4UBUF XIFSF UIF TUBUF JT BMTP UIF WBMVF ZPV


SFUVSO
$)"15&3  45"5& 

get :: State s s
get = ???

&YQFDUFE PVUQVU

Prelude> runState get "curryIsAmaze"


("curryIsAmaze","curryIsAmaze")

 $POTUSVDU B 4UBUF XIFSF UIF SFTVMUJOH TUBUF JT UIF BSHVNFOU


QSPWJEFE BOE UIF WBMVF JT EFGBVMUFE UP VOJU

put :: s -> State s ()


put s = ???

Prelude> runState (put "blah") "woot"


((),"blah")

 3VO UIF 4UBUF XJUI Ԣ BOE HFU UIF TUBUF UIBU SFTVMUT

exec :: State s a -> s -> s


exec (State sa) s = ???

Prelude> exec (put "wilma") "daphne"


"wilma"
Prelude> exec get "scooby papu"
"scooby papu"
$)"15&3  45"5& 

 3VO UIF 4UBUF XJUI Ԣ BOE HFU UIF WBMVF UIBU SFTVMUT

eval :: State s a -> s -> a


eval (State sa) = ???

Prelude> eval get "bunnicula"


"bunnicula"
Prelude> eval get "stake a bunny"
"stake a bunny"

 8SJUF B GVODUJPO XIJDI BQQMJFT B GVODUJPO UP DSFBUF B OFX


4UBUF

modify :: (s -> s) -> State s ()


modify = undefined

4IPVME CFIBWF MJLF UIF GPMMPXJOH

Prelude> runState (modify (+1)) 0


((),1)
Prelude> runState (modify (+1) >> modify (+1)) 0
((),2)

/PUF ZPV EPOƊU OFFE UP DPNQPTF UIFN ZPV DBO KVTU UISPX
BXBZ UIF SFTVMU CFDBVTF JU SFUVSOT VOJU GPS Ԑ BOZXBZ
$)"15&3  45"5& 

 'PMMPXVQ SFTPVSDFT


 4UBUF .POBE "MM "CPVU .POBET )BTLFMM 8JLJ
https://wiki.haskell.org/All_About_Monads

 4UBUF .POBE )BTLFMM 8JLJ


https://wiki.haskell.org/State_Monad

 6OEFSTUBOEJOH .POBET )BTLFMM 8JLJCPPL


$IBQUFS 

1BSTFS DPNCJOBUPST

8JUIJO B DPNQVUFS
OBUVSBM MBOHVBHF JT
VOOBUVSBM

"MBO 1FSMJT


$)"15&3  1"34&3 $0.#*/"5034 

 1BSTFS DPNCJOBUPST


5IF XPSE ƉQBSTFƊ DPNFT GSPN UIF -BUJO XPSE GPS ƌQBSUTƍ BOE
NFBOT UP BOBMZ[F B TFOUFODF BOE MBCFM UIF TZOUBDUJD SPMF PS QBSU
PG TQFFDI PG FBDI DPNQPOFOU -BOHVBHF UFBDIFST PODF FN
QIBTJ[FE UIJT BCJMJUZ CFDBVTF JU GPSDFE TUVEFOUT UP UIJOL DMPTFMZ
BCPVU UIF TUSVDUVSF PG TFOUFODFT UIF SFMBUJPOTIJQT BNPOH UIF
QBSUT BOE UIF DPOOFDUJPO CFUXFFO UIF TUSVDUVSF BOE UIF NFBO
JOH PG UIF XIPMF %JBHSBNNJOH TFOUFODFT XBT BMTP DPNNPO
CFDBVTF JU NBEF QBSTJOH WJTVBM BOE TPNFXIBU DPODSFUF *U JT
OPX DPNNPO UP SFQSFTFOU HSBNNBUJDBM TUSVDUVSFT PG OBUVSBM
MBOHVBHFT BT USFFT TP UIBU B TFOUFODF TVDI BT

Boy plays with dog.

NJHIU CF UIPVHIU UP IBWF BO VOEFSMZJOH SFQSFTFOUBUJPO


TVDI BT

S(entence)
/ \
Boy plays (verb)
(subject) \
with (preposition)
\
dog (object)

8F BSF OPU IFSF UP CFDPNF MJOHVJTUT CVU QBSTJOH JO DPN


QVUFS TDJFODF JT SFMBUFE UP UIF QBSTJOH PG OBUVSBM MBOHVBHF TFO
$)"15&3  1"34&3 $0.#*/"5034 

UFODFT JO TPNF LFZ XBZT 5IF DPSF JEFB PG QBSTJOH JO QSPHSBN


NJOH JT UP BDDFQU TFSJBMJ[FE JOQVU JO UIF GPSN PG B TFRVFODF
PG DIBSBDUFST UFYUVBM EBUB
PS CZUFT SBX CJOBSZ EBUB
BOE UVSO
UIBU JOUP B WBMVF PG B TUSVDUVSFE EBUBUZQF 4FSJBMJ[FE EBUB JT
EBUB UIBU IBT CFFO USBOTMBUFE JOUP B GPSNBU TVDI BT +40/ PS
9.- UIBU DBO CF TUPSFE PS USBOTNJUUFE BDSPTT B OFUXPSL DPO
OFDUJPO 1BSTJOH CSFBLT VQ UIBU DIVOL PG EBUB BOE BMMPXT ZPV
UP ƶOE BOE QSPDFTT UIF QBSUT ZPV DBSF BCPVU
*G XF XSPUF B DPNQVUFS QSPHSBN UP QBSTF B TFOUFODF JOUP
B WFSZ TJNQMJƶFE NPEFM PG &OHMJTI HSBNNBS JU DPVME MPPL
TPNFUIJOH MJLF UIF USFF BCPWF 0ǒFO XIFO XF BSF QBSTJOH
UIJOHT UIF TUSVDUVSFE EBUBUZQF UIBU SFTVMUT XJMM MPPL TPNFUIJOH
MJLF B USFF *O )BTLFMM XF DBO TPNFUJNFT FOE VQ IBWJOH B USFF
KVTU CFDBVTF SFDVSTJWF UZQFT BSF TP FBTZ UP FYQSFTT JO )BTLFMM
*O UIJT DIBQUFS XF XJMM

Ƒ VTF B QBSTJOH MJCSBSZ UP DPWFS UIF CBTJDT PG QBSTJOH

Ƒ EFNPOTUSBUF UIF BXFTPNF QPXFS PG QBSTFS DPNCJOBUPST

Ƒ NBSTIBMM BOE VONBSTIBMM TPNF +40/ EBUB

Ƒ UBML BCPVU UPLFOJ[BUJPO



*G ZPV EP OPU LOPX XIBU +40/ BOE 9.- BSF ZFU USZ OPU UP HFU UPP IVOH VQ PO UIBU
"MM UIBU NBUUFST BU UIJT QPJOU JT UIBU UIFZ BSF TUBOEBSE EBUB GPSNBUT 8FƊMM MPPL BU +40/ JO
NPSF EFUBJM MBUFS JO UIF DIBQUFS
$)"15&3  1"34&3 $0.#*/"5034 

 " GFX NPSF XPSET PG JOUSPEVDUJPO


*O UIJT DIBQUFS XF XJMM OPU MPPL UPP EFFQMZ JOUP UIF UZQFT PG
UIF QBSTJOH MJCSBSJFT XFƊSF VTJOH MFBSO FWFSZ TPSU PG QBSTFS
UIFSF JT PS BSUJTBOBMMZ IBOEDSBǒ BMM PG PVS QBSTJOH GVODUJPOT
PVSTFMWFT
5IFTF BSF UIPSPVHIMZ DPOTJEFSFE EFDJTJPOT 1BSTJOH JT B IVHF
ƶFME PG SFTFBSDI JO JUT PXO SJHIU XJUI DPOOFDUJPOT UIBU TQBO
OBUVSBM MBOHVBHF QSPDFTTJOH MJOHVJTUJDT BOE QSPHSBNNJOH
MBOHVBHF UIFPSZ +VTU UIJT UPQJD DPVME FBTJMZ ƶMM B CPPL JO JUTFMG
JO GBDU JU IBT
 5IF VOEFSMZJOH UZQFT BOE UZQFDMBTTFT PG UIF
MJCSBSJFT XFƊMM CF VTJOH BSF DPNQMJDBUFE 5P CF TVSF JG ZPV
FOKPZ QBSTJOH BOE FYQFDU UP EP JU B MPU UIPTF BSF UIJOHT ZPVƊE
XBOU UP MFBSO UIFZ BSF TJNQMZ PVU PG UIF TDPQF PG UIJT CPPL
5IJT DIBQUFS UBLFT B EJƵFSFOU BQQSPBDI UIBO QSFWJPVT DIBQ
UFST 5IF GPDVT JT PO FOBCMJOH ZPV UP VTF )BTLFMMƊT QBSTJOH
MJCSBSJFT ƈ OPU UP CF B NBTUFS PG QBSTJOH BOE XSJUJOH QBSTFST
JO HFOFSBM 5IJT JT OPU UIF CPUUPNVQ BQQSPBDI ZPV NBZ CF
BDDVTUPNFE UP CZ OFDFTTJUZ XFƊSF XPSLJOH PVUTJEFJO BOE
USZJOH UP DPWFS XIBU ZPVƊSF MJLFMZ UP OFFE %FQFOEJOH PO ZPVS
TQFDJƶD JOUFSFTUT ZPV NBZ ƶOE UIJT DIBQUFS UPP MPOH PS OPU
OFBSMZ MPOH FOPVHI
$)"15&3  1"34&3 $0.#*/"5034 

 6OEFSTUBOEJOH UIF QBSTJOH QSPDFTT


" QBSTFS JT B GVODUJPO UIBU UBLFT TPNF UFYUVBM JOQVU JU DPVME CF
B 4USJOH JO )BTLFMM PS BOPUIFS EBUBUZQF TVDI BT #ZUF4USJOH PS
5FYU
BOE SFUVSOT TPNF TUSVDUVSF BT BO PVUQVU 5IBU TUSVDUVSF
NJHIU CF B USFF GPS FYBNQMF PS BO JOEFYFE NBQ PG MPDBUJPOT
JO UIF QBSTFE EBUB 1BSTFST BOBMZ[F TUSVDUVSF JO DPOGPSNBODF
XJUI SVMFT TQFDJƶFE JO B HSBNNBS XIFUIFS JUƊT B HSBNNBS PG B
IVNBO MBOHVBHF B QSPHSBNNJOH MBOHVBHF PS B GPSNBU TVDI
BT +40/
" QBSTFS DPNCJOBUPS JT B IJHIFSPSEFS GVODUJPO UIBU UBLFT
QBSTFST BT JOQVU BOE SFUVSOT B OFX QBSTFS BT PVUQVU :PV NBZ
SFNFNCFS PVS CSJFG EJTDVTTJPO PG DPNCJOBUPST XBZ CBDL JO
UIF MBNCEB DBMDVMVT DIBQUFS $PNCJOBUPST BSF FYQSFTTJPOT
XJUI OP GSFF WBSJBCMFT
5IF TUBOEBSE GPS XIBU DPOTUJUVUFT B ƌDPNCJOBUPSƍ XJUI SF
TQFDU UP QBSTFS DPNCJOBUPST JT B MJUUMF MPPTFS 1BSTFST BSF GVOD
UJPOT TP QBSTFS DPNCJOBUPST BSF IJHIFSPSEFS GVODUJPOT UIBU
DBO UBLF QBSTFST BT BSHVNFOUT 6TVBMMZ UIF BSHVNFOU QBTTJOH
JT FMJEFE CFDBVTF UIF JOUFSGBDF PG QBSTFST XJMM PǒFO CF MJLF UIF
4UBUF NPOBE XIJDI QFSNJUT 3FBEFSTUZMF JNQMJDJU BSHVNFOU
QBTTJOH "NPOH PUIFS UIJOHT DPNCJOBUPST BMMPX GPS SFDVSTJPO
BOE GPS HMVJOH UPHFUIFS QBSTFST JO B NPEVMBS GBTIJPO UP QBSTF
EBUB BDDPSEJOH UP DPNQMFY SVMFT
'PS DPNQVUFST QBSTJOH JT TPNFUIJOH MJLF SFBEJOH XIFO
ZPVƊSF SFBMMZ ZPVOH 1FSIBQT ZPV XFSF UBVHIU UP USBDF UIF
$)"15&3  1"34&3 $0.#*/"5034 

MFUUFST XJUI ZPVS ƶOHFS GPS QIPOFUJD QSPOVODJBUJPO -BUFS


ZPV XFSF BCMF UP GPMMPX XPSE CZ XPSE UIFO ZPV KVTU TUBSUFE
TDBOOJOH XJUI ZPVS FZFT &WFOUVBMMZ ZPV MFBSOFE IPX UP SFBE
XJUI TVCWPDBMJ[BUJPO

4JODF XF EJEOƊU VTF BO BOBMPHZ GPS .POBE


8FƊSF HPJOH UP SVO UISPVHI TPNF DPEF OPX UIBU XJMM EFNPO
TUSBUF UIF JEFB PG QBSTJOH -FUƊT CFHJO CZ JOTUBMMJOH UIF QBSTJOH
MJCSBSZ trifecta  UIFO XPSL UISPVHI B TIPSU EFNPOTUSBUJPO PG
XIBU JU EPFT 8FƊMM UBML NPSF BCPVU UIF EFTJHO PG trifecta JO B
XIJMF 'PS OPX XFƊSF KVTU HPJOH UP VTF JU JO B TUBUF PG TPNFXIBU
JHOPSBOU CMJTT
0, MFUƊT QVU VQ TPNF DPEF

module LearnParsers where

import Text.Trifecta

stop :: Parser a
stop = unexpected "stop"

unexpected JT B NFBOT PG UISPXJOH FSSPST JO QBSTFST MJLF 5SJ


GFDUB XIJDI BSF BO JOTUBODF PG UIF 1BSTJOH UZQFDMBTT )FSF XFƊSF
VTJOH JU UP NBLF UIF QBSTFS GBJM GPS EFNPOTUSBUJPO QVSQPTFT

8FƊMM CF VTJOH UIJT WFSTJPO PG USJGFDUB
http://hackage.haskell.org/package/trifecta-1.5.2
$)"15&3  1"34&3 $0.#*/"5034 

8IBU EFNPOTUSBUJPO QVSQPTFT

8FƊSF HMBE ZPV BTLFE 5IF CBTJD JEFB CFIJOE B QBSTFS JT UIBU
ZPVƊSF NPWJOH B TPSU PG DVSTPS BSPVOE B MJOFBS TUSFBN PG UFYU
*UƊT TJNQMFTU UP UIJOL PG UIF JOEJWJEVBM VOJUT XJUIJO UIF TUSFBN BT
DIBSBDUFST PS JEFPHSBQIT UIPVHI ZPVƊMM XBOU UP TUBSU UIJOLJOH
PG ZPVS QBSTJOH QSPCMFNT JO DIVOLJFS UFSNT BT ZPV QSPHSFTT
5IF JEFB JT UIBU UIJT DVSTPS JT B CJU MJLF ZPVƊSF SFBEJOH UIF UFYU
XJUI ZPVS ƶOHFS

Julie bit Papuchon


^

5IFO MFU VT TBZ XF QBSTFE UIF XPSE ƌ+VMJFƍ ƈ XFƊWF OPX


DPOTVNFE UIBU JOQVU TP UIF DVSTPS XJMM CF BU ƌCJUƍ

Julie bit Papuchon


^

*G XF XFSFOƊU FYQFDUJOH UIF XPSE ƌCJU ƍ PVS QBSTFS DPVME


GBJM IFSF BOE XFƊE HFU BO FSSPS BU UIF XPSE ƌCJUƍ KVTU MJLF UIBU
)PXFWFS JG XF EJE QBSTF UIF XPSE ƌCJUƍ TVDDFTTGVMMZ BOE UIVT
DPOTVNFE UIBU JOQVU JU NJHIU MPPL TPNFUIJOH MJLF UIJT

Julie bit Papuchon


^

5IF BOBMPHZ XFƊSF VTJOH IFSF JTOƊU QFSGFDU 0OF PG UIF IBSE
FTU QSPCMFNT JO XSJUJOH QBSTFST FTQFDJBMMZ UIF QBSTFS MJCSBSJFT
$)"15&3  1"34&3 $0.#*/"5034 

UIFNTFMWFT JT NBLJOH JU FBTZ UP FYQSFTT UIJOHT UIF XBZ UIF


QSPHSBNNFS XPVME MJLF CVU TUJMM IBWF UIF SFTVMUJOH QBSTFS CF
GBTU

#BDL UP UIF DPEF

8JUI UIF DVSTPS BOBMPHZ JO NJOE MFUƊT SFUVSO UP UIF NPEVMF


XF TUBSUFE
8FƊMM ƶSTU NBLF B MJUUMF GVODUJPO UIBU POMZ QBSTFT POF DIBSBD
UFS BOE UIFO TFRVFODF UIBU XJUI stop UP NBLF JU SFBE UIBU POF
DIBSBDUFS BOE UIFO EJF

-- read a single character '1'


one = char '1'

-- read a single character '1', then die


one' = one >> stop
-- equivalent to char '1' >> stop

'PS one' XFƊSF VTJOH UIF TFRVFODJOH PQFSBUPS GSPN Monad UP


DPNCJOF UXP QBSTFST stop BOE char '1' (JWFO UIF UZQF PG >>

(>>) :: Monad m => m a -> m b -> m b

JUƊT TBGF UP BTTVNF UIBU XIBUFWFS char '1' SFUVSOT JO UIF


FYQSFTTJPO

char '1' >> stop


$)"15&3  1"34&3 $0.#*/"5034 

HFUT UISPXO BXBZ $SJUJDBMMZ BOZ FƵFDU UIF m a BDUJPO IBE


VQPO UIF NPOBEJD DPOUFYU SFNBJOT 5IF SFTVMU WBMVF PG UIF
QBSTF GVODUJPO HFUT UISPXO BXBZ CVU UIF FƵFDU PG ƌNPWJOH UIF
DVSTPSƍ SFNBJOT "OPUIFS QPTTJCMF FƵFDU JT DBVTJOH UIF QBSTF
UP GBJM

" CJU MJLFƒ


4UBUF 1MVT GBJMVSF /P TFSJPVTMZ UBLF B MPPL BU UIJT EFƶOJUJPO
PG UIF 1BSTFS UZQF

type Parser a = String -> Maybe (a, String)

:PV DBO SFBE UIJT BT

 "XBJU B TUSJOH WBMVF

 1SPEVDF B SFTVMU XIJDI NBZ PS NBZ OPU TVDDFFE " /PUI


JOH WBMVF NFBOT UIF QBSTF GBJMFE

 3FUVSO B UVQMF PG UIF WBMVF ZPV XBOUFE BOE XIBUFWFSƊT


MFǒ PG UIF TUSJOH UIBU ZPV EJEOƊU DPOTVNF UP QSPEVDF UIF
WBMVF PG UZQF Ԑ

5IFO SFNJOE ZPVSTFMG PG XIBU 3FBEFS BOE 4UBUF MPPL MJLF

newtype Reader r a = Reader { runReader :: r -> a }

newtype State s a = State { runState :: s -> (a, s) }


$)"15&3  1"34&3 $0.#*/"5034 

*G ZPV IBWF DPOWJODFE ZPVSTFMG UIBU 4UBUF JT BO FMBCPSBUJPO


PG 3FBEFS BOE UIBU ZPV DBO TFF IPX UIF 1BSTFS UZQF MPPLT TPSUB
MJLF 4UBUF XF DBO NPWF PO
5IF JEFB IFSF XJUI UIF 1BSTFS UZQF JT UIBU UIF 4UBUF JT IBO
EMJOH UIF GBDU UIBU ZPV OFFE UP BXBJU BO FWFOUVBM UFYU JOQVU BOE
UIBU IBWJOH QBSTFE TPNFUIJOH PVU PG UIBU UFYU JOQVU SFTVMUT JO
B OFX TUBUF PG UIF JOQVU TUSFBN *U BMTP MFUT ZPV SFUVSO B WBMVF
JOEFQFOEFOU PG UIF TUBUF XIJMF .BZCF IBOEMFT UIF QPTTJCJMJUZ
PG UIF QBSTFS GBJMVSF
*G XF XFSF UP MPPL BU UIF VOEFSMZJOH QBUUFSO PG B QBSTJOH
GVODUJPO TVDI BT char ZPV DBO TFF UIF 4UBUFJTI QBUUFSO 1MFBTF
VOEFSTUBOE UIBU XIJMF UIJT TIPVME XPSL BT B DIBSQBSTJOH GVOD
UJPO XF BSF TJNQMJGZJOH IFSF BOE UIJT JT OPU XIBU UIF TPVSDF
DPEF PG BOZ NPEFSO QBSTJOH MJCSBSZ XJMM MPPL MJLF

-- rudimentary char
-- demo only, this won't work as is.
char :: Char -> Parser Char
char c =
Parser $ \ s ->
case s of
(x:xs) -> if c == x
then [(c, xs)]
else []
_ -> []
$)"15&3  1"34&3 $0.#*/"5034 

8F DPVME FODPEF UIF QPTTJCJMJUZ PG GBJMVSF JO UIBU CZ BEEJOH


.BZCF CVU BU UIJT QPJOU UIBU JTOƊU JNQPSUBOU CFDBVTF XFƊSF
VTJOH B MJCSBSZ UIBU IBT FODPEFE UIF QPTTJCJMJUZ PG GBJMVSF GPS
VT *U IBT BMTP PQUJNJ[FE UIF IFDL PVU PG char GPS VT #VU XF
XBOUFE UP TIPX ZPV IPX UIF VOEFSMZJOH GVODUJPO JT UIF s ->
FNCFEEFE JO UIF 1BSTFS EBUB DPOTUSVDUPS
$POTJEFS UIF UZQF PG B )VUUPO.FJKFS QBSTFS

-- from Text.ParserCombinators.HuttonMeijer
-- polyparse-1.11

type Token = Char


newtype Parser a =
P ([Token] -> [(a, [Token])])

-- Same thing, differently formatted:


type Parser' a = String -> [(a, String)]

5IJT DIBOHFT UIJOHT GSPN UIF QSFWJPVT MFTT DPNNPO CVU


TJNQMFS WBSJBOU CZ BMMPXJOH ZPV UP FYQSFTT B SBOHF PG QPTTJCMZ
WBMJE QBSTFT TUBSUJOH GSPN UIF JOQVU QSPWJEFE 5IJT JT NPSF
QPXFSGVM UIBO UIF .BZCF WBSJBOU CVU UIJT EFTJHO JTOƊU VTFE JO
QPQVMBS )BTLFMM QBSTFS DPNCJOBUPS MJCSBSJFT BOZ MPOHFS "M
UIPVHI UIF VOEFSMZJOH JNQMFNFOUBUJPO IBT DIBOHFE ESBNBUJ
DBMMZ XJUI OFX EJTDPWFSJFT BOE EFTJHOT NPTU QBSTJOH MJCSBSJFT
JO )BTLFMM BSF HPJOH UP IBWF BO JOUFSGBDF UIBU CFIBWFT B CJU MJLF
$)"15&3  1"34&3 $0.#*/"5034 

4UBUF JO UIBU UIF BDU PG QBSTJOH UIJOHT IBT BO PCTFSWBCMF FƵFDU


PO POF PS NPSF CJUT PG TUBUF
*G XF XFSF UBMLJOH BCPVU 4UBUF UIJT NFBOT BOZ put UP UIF
4UBUF WBMVF XPVME CF PCTFSWBCMF UP UIF OFYU BDUJPO JO UIF TBNF
.POBE ZPV DBO WFSJGZ XIBU GPMMPXT JO ZPVS 3&1- CZ JNQPSU
JOH $POUSPM.POBE5SBOT4UBUF
 5IFTF FYBNQMFT VTF UIF USBOT
GPSNFS WBSJBOU PG 4UBUF CVU JG ZPV JHOPSF UIF 5 ZPV TIPVME CF
BCMF UP HFU UIF CBTJD JEFB

get :: Monad m => StateT s m s


put :: Monad m => s -> StateT s m ()
runStateT :: StateT s m a -> s -> m (a, s)

Prelude> runStateT (put 8) 7


((),8)
Prelude> runStateT get 8
(8,8)
Prelude> runStateT (put 1 >> get) 8
(1,1)
Prelude> (runStateT $ put 1 >> get) 0
(1,1)
Prelude> (runStateT $ put 2 >> get) 10021490234890
(2,2)
Prelude> (runStateT $ put 2 >> return 9001) 0
(9001,2)
$)"15&3  1"34&3 $0.#*/"5034 

/PX put SFUVSOT B VOJU WBMVF B UISPXBXBZ WBMVF TP XFƊSF


POMZ FWBMVBUJOH JU GPS FƵFDU BOZXBZ *U NPEJƶFT UIF TUBUF CVU
EPFTOƊU IBWF BOZ WBMVF PG JUT PXO 4P XIFO XF UISPX BXBZ JUT
ƌWBMVF ƍ XFƊSF MFǒ XJUI JUT FƵFDU PO UIF TUBUF BMUIPVHI get QVUT
UIBU WBMVF JOUP CPUI UIF Ԑ BOE Ԣ TMPUT JO UIF UVQMF
5IJT JT BO BXGVM MPU MJLF XIBU IBQQFOT XIFO XF TFRVFODF B
QBSTJOH GVODUJPO TVDI BT char XJUI stop BT BCPWF 5IFSF JT OP
SFBM SFTVMU PG char CVU JU EPFT DIBOHF UIF ƌTUBUFƍ 5IF TUBUF IFSF
JT UIF MPDBUJPO PG UIF DVSTPS JO UIF JOQVU TUSFBN *O SFBMJUZ B
NPEFSO BOE NBUVSF QBSTFS EFTJHO JO )BTLFMM XJMM PǒFO MPPL
BCPVU BT GBNJMJBS UP ZPV BT UIF BMJFO IFMMTDBQF VOEFSOFBUI UIF
GSP[FO DSVTU PG POF PG UIF NPPOT PG +VQJUFS %POƊU UBLF UIF
JEFB PG UIFSF CFJOH BO BDUVBM DVSTPS UPP MJUFSBMMZ CVU UIFSF NBZ
CF TPNF VUJMJUZ JO JNBHJOJOH JU UIJT XBZ

#BDL UP PVS SFHVMBSMZ TDIFEVMFE DPEJOH


0OXBSE XJUI UIF DPEF
$)"15&3  1"34&3 $0.#*/"5034 

-- read two characters, '1', and '2'


oneTwo = char '1' >> char '2'

-- read two characters, '1' and '2', then die


oneTwo' = oneTwo >> stop

testParse :: Parser Char -> IO ()


testParse p =
print $ parseString p mempty "123"

5IF ԟ BSHVNFOU JT B QBSTFS 4QFDJƶDBMMZ JUƊT B DIBSBDUFS


QBSTFS 5IF GVODUJPOT one BOE oneTwo IBWF UIF UZQF Parser Char
:PV DBO DIFDL UIF UZQFT PG one' BOE oneTwo' ZPVSTFMG
8F OFFEFE UP EFDMBSF UIF UZQF PG testParse JO PSEFS UP TIPX
XIBU XF QBSTFE CFDBVTF PG BNCJHVJUZ
5IF LFZ UIJOH UP SFBMJ[F IFSF JT UIBU XFƊSF VTJOH QBSTFST
MJLF WBMVFT BOE DPNCJOJOH UIFN VTJOH UIF TBNF TUVƵ XF VTF
XJUI PSEJOBSZ GVODUJPOT PS PQFSBUPST GSPN UIF "QQMJDBUJWF
BOE .POBE UZQFDMBTTFT 5IF ƌTUSVDUVSFƍ UIBU NBLFT VQ UIF
"QQMJDBUJWF PS .POBE JO UIJT DBTF JT UIF 1BSTFS JUTFMG
/FYU XFƊMM XSJUF B GVODUJPO UP QSJOU B TUSJOH UP TUBOEBSE
PVUQVU TUEPVU
XJUI B OFXMJOF QSFƶYFE BOE UIFO VTF UIBU
GVODUJPO BT QBSU PG B main GVODUJPO UIBU XJMM TIPX VT XIBU XFƊWF
HPU TP GBS
$)"15&3  1"34&3 $0.#*/"5034 

pNL s =
putStrLn ('\n' : s)

main = do
pNL "stop:"
testParse stop
pNL "one:"
testParse one
pNL "one':"
testParse one'
pNL "oneTwo:"
testParse oneTwo
pNL "oneTwo':"
testParse oneTwo'

-FUƊT SVO JU BOE JOUFSQSFU UIF SFTVMUT 4JODF JUƊT UFYU PO B


DPNQVUFS TDSFFO JOTUFBE PG UFB MFBWFT XFƊMM DBMM JU TDJFODF *G
ZPV SFNBJO VODPOWJODFE ZPV IBWF PVS QFSNJTTJPO UP EPO B
XIJUF MBCDPBU BOE QSJOU UIF PVUQVU VTJOH B EPUNBUSJY QSJOUFS
4PNF PG ZPV LJET QSPCBCMZ EPOƊU FWFO LOPX XIBU B EPUNBUSJY
QSJOUFS JT
3VO UIF main GVODUJPO BOE TFF XIBU IBQQFOT

Prelude> main


TIBLFT ƶTU BU TLZ
$)"15&3  1"34&3 $0.#*/"5034 

stop:
Failure (interactive):1:1: error: unexpected
stop
123<EOF>
^

8F GBJMFE JNNFEJBUFMZ CFGPSF DPOTVNJOH BOZ JOQVU JO UIF


BCPWF TP UIF DBSFU JO UIF FSSPS JT BU UIF CFHJOOJOH PG PVS TUSJOH
WBMVF
/FYU SFTVMU

one:
Success '1'

8F QBSTFE B TJOHMF DIBSBDUFS UIF EJHJU  5IF SFTVMU JT LOPX


JOH XF TVDDFFEFE #VU XIBU BCPVU UIF SFTU PG UIF JOQVU TUSFBN
8FMM UIF UIJOH XF VTFE UP SVO UIF QBSTFS ESPQQFE UIF SFTU PG
UIF JOQVU PO UIF ƷPPS 5IFSF BSF XBZT UP DIBOHF UIJT CFIBWJPS
XIJDI XFƊMM FYQMBJO JO UIF FYFSDJTFT
/FYU VQ

one':
Failure (interactive):1:2: error: unexpected
stop
123<EOF>
^
$)"15&3  1"34&3 $0.#*/"5034 

8F QBSTFE B TJOHMF DIBSBDUFS TVDDFTTGVMMZ UIFO ESPQQFE JU


CFDBVTF XF VTFE >> UP TFRVFODF JU XJUI stop 5IJT NFBOT UIF
DVSTPS XBT POF DIBSBDUFS GPSXBSE EVF UP UIF QSFWJPVT QBSTFS
TVDDFFEJOH )FMQGVMMZ 5SJGFDUB UFMMT VT XIFSF PVS QBSTFS GBJMFE
"OE GPS PVS MBTU SFTVMU

oneTwo:
Success '2'

oneTwo':
Failure (interactive):1:3: error: unexpected
stop
123<EOF>
^

*UƊT UIF TBNF BT CFGPSF CVU XF QBSTFE UXP DIBSBDUFST JOEJ


WJEVBMMZ 8IBU JG XF XF EPOƊU XBOU UP EJTDBSE UIF ƶSTU DIBSBDUFS
XF QBSTFE BOE JOTUFBE QBSTF ƌ ƍ 4FF UIF FYFSDJTFT CFMPX

&YFSDJTFT 1BSTJOH 1SBDUJDF


 5IFSFƊT B DPNCJOBUPS UIBUƊMM MFU VT NBSL UIBU XF FYQFDU
BO JOQVU TUSFBN UP CF ƌƶOJTIFEƍ BU B QBSUJDVMBS QPJOU JO
PVS QBSTFS *O UIF parsers MJCSBSZ UIJT JT TJNQMZ DBMMFE eof
FOEPGƶMF
BOE JT JO UIF Text.Parser.Combinators NPEVMF
4FF JG ZPV DBO NBLF UIF one BOE oneTwo QBSTFST GBJM CFDBVTF
UIFZ EJEOƊU FYIBVTU UIF JOQVU TUSFBN
$)"15&3  1"34&3 $0.#*/"5034 

 6TF string UP NBLF B 1BSTFS UIBU QBSTFT ƌƍ ƌƍ BOE ƌƍ
PVU PG UIF FYBNQMF JOQVU SFTQFDUJWFMZ 5SZ DPNCJOJOH JU
XJUI stop UPP 5IBU JT B TJOHMF QBSTFS TIPVME CF BCMF UP
QBSTF BMM UISFF PG UIPTF TUSJOHT

 5SZ XSJUJOH B 1BSTFS UIBU EPFT XIBU string EPFT CVU VTJOH
char

*OUFSNJTTJPO QBSTJOH GSFF KB[[


-FU VT QMBZ XJUI UIFTF QBSTFST 8F UZQJDBMMZ VTF UIF parseString
GVODUJPO UP SVO QBSTFST CVU JG ZPV ƶHVSF TPNF PUIFS XBZ UIBU
XPSLT GPS ZPV TP CF JU )FSFƊT TPNF QBSTJOH GSFF KB[[ JG ZPV
XJMM NFBOU POMZ UP IFMQ EFWFMPQ ZPVS JOUVJUJPO BCPVU XIBUƊT
HPJOH PO

Prelude> import Text.Trifecta


Prelude> :t char
char :: CharParsing m => Char -> m Char
Prelude> :t parseString
parseString
:: Parser a
-> Text.Trifecta.Delta.Delta
-> String
-> Result a
Prelude> let gimmeA = char 'a'
Prelude> :t parseString gimmeA mempty
$)"15&3  1"34&3 $0.#*/"5034 

parseString gimmeA mempty :: String -> Result Char

Prelude> parseString gimmeA mempty "a"


Success 'a'
Prelude> parseString gimmeA mempty "b"
Failure (interactive):1:1: error: expected: "a"
b<EOF>
^

Prelude> parseString (char 'b') mempty "b"


Success 'b'
Prelude> parseString (char 'b' >> char 'c') mempty "b"
Failure (interactive):1:2: error: unexpected
EOF, expected: "c"
b<EOF>
^
Prelude> parseString (char 'b' >> char 'c') mempty "bc"
Success 'c'
Prelude> parseString (char 'b' >> char 'c') mempty "abc"
Failure (interactive):1:1: error: expected: "b"
abc<EOF>
^

4FFNT MJLF XF PVHIU UP IBWF B XBZ UP TBZ ƌQBSTF UIJT TUSJOHƍ


SBUIFS UIBO IBWJOH UP TFRVFODF UIF QBSTFST PG JOEJWJEVBM DIBS
BDUFST CJU CZ CJU SJHIU 5VSOT PVU XF EP
$)"15&3  1"34&3 $0.#*/"5034 

Prelude> parseString (string "abc") mempty "abc"


Success "abc"
Prelude> parseString (string "abc") mempty "bc"
Failure (interactive):1:1: error: expected: "abc"
bc<EOF>
^
Prelude> parseString (string "abc") mempty "ab"
Failure (interactive):1:1: error: expected: "abc"
ab<EOF>
^

*NQPSUBOUMZ JUƊT OPU B HJWFO UIBU B TJOHMF QBSTFS FYIBVTUT BMM


PG JUT JOQVU ƈ UIFZ POMZ DPOTVNF BT NVDI UFYU BT UIFZ OFFE
UP QSPEVDF UIF WBMVF PG UIF UZQF SFRVFTUFE

Prelude> parseString (char 'a') mempty "abcdef"


Success 'a'
Prelude> let stop = unexpected "stop pls"
Prelude> parseString (char 'a' >> stop) mempty "abcdef"
Failure (interactive):1:2: error: unexpected
stop pls
abcdef<EOF>
^
Prelude> parseString (string "abc") mempty "abcdef"
Success "abc"
Prelude> parseString (string "abc" >> stop) mempty "abcdef"
$)"15&3  1"34&3 $0.#*/"5034 

Failure (interactive):1:4: error: unexpected


stop pls
abcdef<EOF>
^

/PUF UIBU XF DBO BMTP QBSTF 65' FODPEFE #ZUF4USJOHT


XJUI 5SJGFDUB

Prelude> import Text.Trifecta


Prelude> :t parseByteString
parseByteString
:: Parser a
-> Text.Trifecta.Delta.Delta
-> Data.ByteString.Internal.ByteString
-> Result a
Prelude> parseByteString (char 'a') mempty "a"
Success 'a'

5IJT FOET UIF GSFF KB[[ TFTTJPO 8F OPX SFUVSO UP TFSJPVT


NBUUFST

 1BSTJOH GSBDUJPOT


/PX UIBU XF IBWF TPNF JEFB PG XIBU QBSTJOH JT XIBU QBSTFS
DPNCJOBUPST BSF BOE XIBU UIF NPOBEJD VOEFSQJOOJOHT PG
QBSTJOH MPPL MJLF MFUƊT NPWF PO UP QBSTJOH GSBDUJPOT 5IF UPQ
PG UIJT NPEVMF TIPVME MPPL MJLF UIJT
$)"15&3  1"34&3 $0.#*/"5034 

{-# LANGUAGE OverloadedStrings #-}

module Text.Fractions where

import Control.Applicative
import Data.Ratio ((%))
import Text.Trifecta

8F OBNFE UIF NPEVMF Text.Fractions CFDBVTF XFƊSF QBSTJOH


GSBDUJPOT PVU PG UFYU JOQVU BOE UIFSFƊT OP OFFE UP CF NPSF DMFWFS
BCPVU JU UIBO UIBU 8FƊSF HPJOH UP CF VTJOH 4USJOH JOQVUT XJUI
trifecta BU ƶSTU CVU ZPVƊMM TFF XIZ XF UISFX BO 0WFSMPBEFE
4USJOHT QSBHNB JO UIFSF MBUFS
/PX PO UP QBSTJOH GSBDUJPOT 8FƊMM TUBSU XJUI TPNF UFTU
JOQVUT

badFraction = "1/0"
alsoBad = "10"
shouldWork = "1/2"
shouldAlsoWork = "2/1"

5IFO XFƊMM XSJUF PVS BDUVBM QBSTFS


$)"15&3  1"34&3 $0.#*/"5034 

parseFraction :: Parser Rational


parseFraction = do
numerator <- decimal
-- [2] [1]
char '/'
-- [3]
denominator <- decimal
-- [ 4 ]
return (numerator % denominator)
-- [5] [6]

 decimal :: Integral a => Parser a

5IJT JT UIF UZQF PG decimal XJUIJO UIF DPOUFYU PG UIPTF


GVODUJPOT *G ZPV VTF ()$J UP RVFSZ UIF UZQF PG decimal
ZPV XJMM TFF B NPSF QPMZNPSQIJD UZQF TJHOBUVSF

 )FSF OVNFSBUPS IBT UIF UZQF Integral a => a

 char :: Char -> Parser Char

"T XJUI decimal JG ZPV RVFSZ UIF UZQF PG char JO ()$J


ZPVƊMM TFF B NPSF QPMZNPSQIJD UZQF CVU UIJT JT UIF UZQF
PG char JO DPOUFYU

 4BNF EFBM BT OVNFSBUPS CVU XIFO XF NBUDI BO JOUFHSBM


OVNCFS XFƊSF CJOEJOH UIF SFTVMU UP UIF OBNF ƌEFOPNJOB
UPSƍ
$)"15&3  1"34&3 $0.#*/"5034 

 5IF ƶOBM SFTVMU IBT UP CF B QBSTFS TP XF FNCFE PVS JOUF


HSBM WBMVF JO UIF 1BSTFS UZQF CZ VTJOH SFUVSO

 8F DPOTUSVDU SBUJPT VTJOH UIF % JOƶY PQFSBUPS

(%) :: Integral a => a -> a -> GHC.Real.Ratio a

5IFO UIF GBDU UIBU PVS ƶOBM SFTVMU JT B 3BUJPOBM NBLFT UIF
Integral a => a WBMVFT JOUP DPODSFUF *OUFHFS WBMVFT

type Rational = GHC.Real.Ratio Integer

8FƊMM QVU UPHFUIFS B RVJDL TIJN NBJO GVODUJPO UP SVO UIF


QBSTFS BHBJOTU UIF UFTU JOQVUT BOE TFF UIF SFTVMUT

main :: IO ()
main = do
print $ parseString parseFraction mempty shouldWork
print $ parseString parseFraction mempty shouldAlsoWork
print $ parseString parseFraction mempty alsoBad
print $ parseString parseFraction mempty badFraction

5SZ OPU UP XPSSZ BCPVU UIF mempty WBMVFT JU NJHIU HJWF ZPV
B DMVF BCPVU XIBUƊT HPJOH PO JO trifecta VOEFS UIF IPPE CVU
JUƊT OPU TPNFUIJOH XFƊSF HPJOH UP FYQMPSF JO UIJT DIBQUFS
8F XJMM CSJFƷZ OPUF UIF UZQF PG parseString XIJDI JT IPX
XFƊSF SVOOJOH UIF QBSTFS XF DSFBUFE
$)"15&3  1"34&3 $0.#*/"5034 

parseString :: Parser a
-> Text.Trifecta.Delta.Delta
-> String
-> Result a

5IF ƶSTU BSHVNFOU JT UIF QBSTFS XFƊSF HPJOH UP SVO BHBJOTU


UIF JOQVU UIF TFDPOE JT B %FMUB UIF UIJSE JT UIF 4USJOH XFƊSF
QBSTJOH BOE UIFO UIF ƶOBM SFTVMU JT FJUIFS UIF UIJOH XF XBOUFE
PG UZQF Ԑ PS BO FSSPS TUSJOH UP MFU VT LOPX TPNFUIJOH XFOU
XSPOH :PV DBO JHOPSF UIF %FMUB UIJOH ƈ KVTU VTF mempty UP
QSPWJEF UIF EPOPUIJOH JOQVU 8F XPOƊU CF DPWFSJOH EFMUBT JO
UIJT CPPL TP DPOTJEFS JU FYUSB DSFEJU JG ZPV HFU DVSJPVT
"OZXBZ XIFO XF SVO UIF DPEF UIF SFTVMUT MPPL MJLF UIJT

Prelude> main
Success (1 % 2)
Success (2 % 1)
Failure (interactive):1:3: error: unexpected
EOF, expected: "/", digit
10<EOF>
^
Success *** Exception: Ratio has zero denominator

5IF ƶSTU UXP TVDDFFEFE QSPQFSMZ 5IF UIJSE GBJMFE CFDBVTF JU


DPVMEOƊU QBSTF B GSBDUJPO PVU PG UIF UFYU ƌƍ 5IF FSSPS JT UFMMJOH
VT UIBU JU SBO PVU PG UFYU JO UIF JOQVU TUSFBN XIJMF TUJMM XBJUJOH
GPS UIF DIBSBDUFS '/' 5IF ƶOBM FSSPS EJE OPU SFTVMU GSPN UIF
$)"15&3  1"34&3 $0.#*/"5034 

QSPDFTT PG QBSTJOH XF LOPX UIBU CFDBVTF JU JT B Success EBUB


DPOTUSVDUPS 5IF ƶOBM FSSPS SFTVMUFE GSPN USZJOH UP DPOTUSVDU
B SBUJP XJUI B EFOPNJOBUPS UIBU JT [FSP ƈ XIJDI NBLFT OP
TFOTF 8F DBO SFQSPEVDF UIF JTTVF JO ()$J

Prelude> 1 % 0
*** Exception: Ratio has zero denominator
-- So the parser result is which is tantamount to
Prelude> Success (1 % 0)
Success *** Exception: Ratio has zero denominator

5IJT JT TPSU PG B QSPCMFN CFDBVTF FYDFQUJPOT FOE PVS QSP


HSBNT 0CTFSWF

main :: IO ()
main = do
print $ parseString parseFraction mempty badFraction
print $ parseString parseFraction mempty shouldWork
print $ parseString parseFraction mempty shouldAlsoWork
print $ parseString parseFraction mempty alsoBad

8FƊWF QVU UIF FYQSFTTJPO UIBU UISPXT BO FYDFQUJPO JO UIF


ƶSTU MJOF UIJT UJNF XIFO XF SVO JU XF HFU

Prelude> main
Success *** Exception: Ratio has zero denominator
$)"15&3  1"34&3 $0.#*/"5034 

4P PVS QSPHSBN IBMUFE PO UIF FSSPS 5IJT JT OPU HSFBU 5IF


JNQVMTF PG BO FYQFSJFODFE QSPHSBNNFS JT MJLFMZ UP CF UP XBOU
UP ƌIBOEMFƍ UIF FSSPS :PV EP OPU XBOU UP BUUFNQU UP DBUDI
PS IBOEMF FYDFQUJPOT $BUDIJOH FYDFQUJPOT JT PLBZ CVU UIJT
JT B QBSUJDVMBS DMBTT PG FYDFQUJPOT UIBU NFBOT TPNFUIJOH JT
RVJUF XSPOH XJUI ZPVS QSPHSBN :PV TIPVME FMJNJOBUF UIF
QPTTJCJMJUZ PG FYDFQUJPOT PDDVSSJOH JO ZPVS QSPHSBNT XIFSF
QPTTJCMF
8FƊMM UBML NPSF BCPVU FSSPS IBOEMJOH JO B MBUFS DIBQUFS CVU
UIF JEFB IFSF JT UIBU B 1BSTFS UZQF BMSFBEZ FYQMJDJUMZ FODPEFT
UIF QPTTJCJMJUZ PG GBJMVSF *UƊT CFUUFS GPS B WBMVF PG UZQF Parser
a UP IBWF POMZ POF WFDUPS GPS FSSPST BOE UIBU WFDUPS JT UIF
QBSTFSƊT BCJMJUZ UP FODPEF GBJMVSF 5IFSF NBZ CF BO FEHF DBTF
UIBU EPFTOƊU TVJU UIJT EFTJHO QSFGFSFODF CVU JUƊT B WFSZ HPPE
JEFB UP OPU IBWF FYDFQUJPOT PS CPUUPNT UIBU BSFOƊU FYQMJDJUMZ
DBMMFE PVU BT B QPTTJCJMJUZ JO UIF UZQFT XIFOFWFS QPTTJCMF
*G XF XFSF GFFMJOH LFFO UP CF B EPHPPEFS XF DPVME NPEJGZ
PVS QSPHSBN UP IBOEMF UIF  EFOPNJOBUPS DBTF BOE DIBOHF JU
JOUP B QBSTF FSSPS
$)"15&3  1"34&3 $0.#*/"5034 

virtuousFraction :: Parser Rational


virtuousFraction = do
numerator <- decimal
char '/'
denominator <- decimal
case denominator of
0 -> fail "Denominator cannot be zero"
_ -> return (numerator % denominator)

)FSF JT PVS ƶSTU FYQMJDJU VTF PG fail XIJDI CZ IJTUPSJDBM


BDDJEFOU JT QBSU PG UIF .POBE UZQFDMBTT 3FBMJTUJDBMMZ OPU BMM
.POBET IBWF B QSPQFS JNQMFNFOUBUJPO PG fail TP JU XJMM CF
NPWFE PVU JOUP B MonadFail DMBTT FWFOUVBMMZ 'PS OPX JU TVƸDFT
UP LOPX UIBU JU JT PVS NFBOT PG SFUVSOJOH BO FSSPS GPS UIF 1BSTFS
UZQF IFSF
/PX GPS BOPUIFS SVO PG PVS UFTU JOQVUT CVU XJUI PVS NPSF
DBVUJPVT QBSTFS

testVirtuous :: IO ()
testVirtuous = do
print $ parseString virtuousFraction mempty badFraction
print $ parseString virtuousFraction mempty alsoBad
print $ parseString virtuousFraction mempty shouldWork
print $ parseString virtuousFraction mempty shouldAlsoWork

8IFO XF SVO UIJT XFƊSF HPJOH UP HFU B TMJHIUMZ EJƵFSFOU


SFTVMU BU UIF FOE
$)"15&3  1"34&3 $0.#*/"5034 

Prelude> testVirtuous
Failure (interactive):1:4: error: Denominator
cannot be zero, expected: digit
1/0<EOF>
^
Failure (interactive):1:3: error: unexpected
EOF, expected: "/", digit
10<EOF>
^
Success (1 % 2)
Success (2 % 1)

/PX XF IBWF OP CPUUPN DBVTJOH UIF QSPHSBN UP IBMU BOE


XF HFU B 'BJMVSF WBMVF XIJDI FYQMBJOT UIF DBVTF GPS UIF GBJMVSF
.VDI CFUUFS

&YFSDJTF 6OJU PG 4VDDFTT


5IJT TIPVME OPU CF VOGBNJMJBS BU UIJT QPJOU FWFO JG ZPV EP OPU
VOEFSTUBOE BMM UIF EFUBJMT

Prelude> parseString integer mempty "123abc"


Success 123
Prelude> parseString (integer >> eof) mempty "123abc"
Failure (interactive):1:4: error: expected: digit,
end of input
123abc<EOF>
$)"15&3  1"34&3 $0.#*/"5034 

^
Prelude> parseString (integer >> eof) mempty "123"
Success ()

:PV NBZ IBWF BMSFBEZ EFEVDFE XIZ JU SFUVSOT () BT B 4VDDFTT


SFTVMU IFSF JUƊT DPOTVNFE BMM UIF JOQVU CVU UIFSF JT OP SFTVMU
UP SFUVSO GSPN IBWJOH EPOF TP 5IF SFTVMU Success () UFMMT ZPV
UIF QBSTF XBT TVDDFTTGVM BOE DPOTVNFE UIF FOUJSF JOQVU TP
UIFSFƊT OPUIJOH UP SFUVSO
8IBU XF XBOU ZPV UP USZ OPX JT SFXSJUJOH UIF ƶOBM FYBNQMF
TP JU SFUVSOT UIF JOUFHFS UIBU JU QBSTFE JOTUFBE PG Success ()
*U TIPVME SFUVSO UIF JOUFHFS TVDDFTTGVMMZ XIFO JU SFDFJWFT BO
JOQVU XJUI BO JOUFHFS GPMMPXFE CZ BO &0' BOE GBJM JO BMM PUIFS
DBTFT

Prelude> parseString (yourFuncHere) mempty "123"


Success 123
Prelude> parseString (yourFuncHere) mempty "123abc"
Failure (interactive):1:4: error: expected: digit,
end of input
123abc<EOF>
^

 )BTLFMMƊT QBSTJOH FDPTZTUFN


)BTLFMM IBT TFWFSBM FYDFMMFOU QBSTJOH MJCSBSJFT BWBJMBCMF parsec
BOE attoparsec BSF QFSIBQT UIF UXP NPTU XFMM LOPXO QBSTFS
$)"15&3  1"34&3 $0.#*/"5034 

DPNCJOBUPS MJCSBSJFT JO )BTLFMM CVU UIFSF JT BMTP megaparsec


BOE PUIFST aeson BOE cassava BSF BNPOH UIF MJCSBSJFT EFTJHOFE
GPS QBSTJOH TQFDJƶD UZQFT PG EBUB +40/ EBUB BOE $47 EBUB
SFTQFDUJWFMZ

'PS UIJT DIBQUFS XF PQUFE UP VTF trifecta BT ZPVƊWF TFFO
0OF SFBTPO GPS UIBU EFDJTJPO JT UIBU trifecta IBT FSSPS NFTTBHFT
UIBU BSF WFSZ FBTZ UP SFBE BOE JOUFSQSFU VOMJLF TPNF PUIFS
MJCSBSJFT "MTP trifecta EPFT OPU TFFN MJLFMZ UP VOEFSHP NBKPS
DIBOHFT JO JUT GVOEBNFOUBM EFTJHO *UT EFTJHO JT TPNFXIBU
VOVTVBM BOE DPNQMFY CVU NPTU PG UIF UIJOHT UIBU NBLF JU
VOVTVBM XJMM CF JSSFMFWBOU UP ZPV JO UIJT DIBQUFS *G ZPV JOUFOE
UP EP B MPU PG QBSTJOH JO QSPEVDUJPO ZPV NBZ OFFE UP HFU
DPNGPSUBCMF VTJOH attoparsec BT JU JT QBSUJDVMBSMZ LOPXO GPS
WFSZ TQFFEZ QBSTJOH ZPV XJMM TFF TPNF attoparsec BOE aeson

MBUFS JO UIF DIBQUFS


5IF EFTJHO PG trifecta IBT FWPMWFE TVDI UIBU UIF "1* JT TQMJU
BDSPTT UXP MJCSBSJFT parsers BOE trifecta 5IF SFBTPO GPS UIJT
JT UIBU UIF trifecta QBDLBHF JUTFMG QSPWJEFT UIF DPODSFUF JNQMF
NFOUBUJPO PG UIF 5SJGFDUB QBSTFS BT XFMM BT 5SJGFDUBTQFDJƶD
GVODUJPOBMJUZ CVU UIF parsers "1* JT B DPMMFDUJPO PG UZQFDMBTTFT
UIBU BCTUSBDU PWFS EJƵFSFOU LJOET PG UIJOHT QBSTFST DBO EP 5IF

"1* TUBOET GPS BQQMJDBUJPO QSPHSBNNJOH JOUFSGBDF 8IFO XF XSJUF TPǒXBSF UIBU
SFMJFT PO MJCSBSJFT PS NBLFT SFRVFTUT UP B TFSWJDF TVDI BT 5XJUUFS ƈ CBTJDBMMZ TPǒXBSF
UIBU SFMJFT PO PUIFS TPǒXBSF ƈ XF SFMZ PO B TFU PG EFƶOFE GVODUJPOT 5IF "1* JT UIBU TFU
PG GVODUJPOT UIBU XF VTF UP JOUFSGBDF XJUI UIBU TPǒXBSF XJUIPVU IBWJOH UP XSJUF UIPTF
GVODUJPOT PS XPSSZ UPP NVDI BCPVU UIFJS TPVSDF DPEF 8IFO ZPV MPPL BU B MJCSBSZ PO
)BDLBHF VOMFTT ZPV DMJDL UP WJFX UIF TPVSDF DPEF
XIBU ZPVƊSF MPPLJOH BU JT UIF "1* GPS
UIBU MJCSBSZ

http://hackage.haskell.org/package/parsers
$)"15&3  1"34&3 $0.#*/"5034 

Text.Trifecta NPEVMF IBOEMFT FYQPSUJOH XIBU ZPV OFFE UP HFU


TUBSUFE GSPN FBDI QBDLBHF TP UIJT JOGPSNBUJPO JT NPTUMZ TP
ZPV LOPX XIFSF UP MPPL JG ZPV OFFE UP TUBSU TQFMVOLJOH

5ZQFDMBTTFT PG 1BSTFST
"T XF OPUFE BCPWF trifecta SFMJFT PO UIF parsers MJCSBSZ GPS
DFSUBJO UZQFDMBTTFT 5IFTF UZQFDMBTTFT BCTUSBDU PWFS DPNNPO
LJOET PG UIJOHT QBSTFST EP 8FƊSF POMZ HPJOH UP OPUF B GFX
UIJOHT IFSF UIBU XFƊMM CF TFFJOH JO UIF DIBQUFS TP UIBU ZPV IBWF
B TFOTF PG UIFJS QSPWFOBODF
/PUF UIBU UIF GPMMPXJOH JT B EJTDVTTJPO PG DPEF QSPWJEFE GPS
ZPV CZ UIF parsers MJCSBSZ ZPV EP OPU OFFE UP UZQF UIJT JO

 5IF UZQFDMBTT Parsing IBT Alternative BT B TVQFSDMBTT 8FƊMM


UBML NPSF BCPVU "MUFSOBUJWF JO B CJU 5IF 1BSTJOH UZQFDMBTT
QSPWJEFT GPS GVODUJPOBMJUZ OFFEFE UP EFTDSJCF QBSTFST JO
EFQFOEFOU PG JOQVU UZQF " NJOJNBM DPNQMFUF JOTUBODF PG
UIJT UZQFDMBTT EFƶOFT UIF GPMMPXJOH GVODUJPOT try (<?>)
BOE notFollowedBy -FUƊT TUBSU XJUI try

-- Text.Parser.Combinators
class Alternative m => Parsing m where
try :: m a -> m a

5IJT UBLFT B QBSTFS UIBU NBZ DPOTVNF JOQVU BOE PO GBJMVSF


HPFT CBDL UP XIFSF JU TUBSUFE BOE GBJMT JG XF EJEOƊU DPOTVNF
$)"15&3  1"34&3 $0.#*/"5034 

JOQVU
*U BMTP HJWFT VT UIF GVODUJPO notFollowedBy XIJDI EPFT OPU
DPOTVNF JOQVU CVU BMMPXT VT UP NBUDI PO LFZXPSET CZ
NBUDIJOH PO B TUSJOH PG DIBSBDUFST UIBU JT OPU GPMMPXFE CZ
TPNF UIJOH XF EP OPU XBOU UP NBUDI

notFollowedBy :: Show a => m a -> m ()


-- > noAlpha = notFollowedBy alphaNum
-- > keywordLet = try $ string "let" <* noAlpha

 5IF 1BSTJOH UZQFDMBTT BMTP JODMVEFT unexpected XIJDI JT


VTFE UP FNJU BO FSSPS PO BO VOFYQFDUFE UPLFO BT XF TBX
FBSMJFS BOE eof 5IF eof GVODUJPO POMZ TVDDFFET BU UIF FOE
PG JOQVU

eof :: m ()
-- > eof = notFollowedBy anyChar <?> "end of input"

8FƊMM CF TFFJOH NPSF PG UIJT POF JO VQDPNJOH TFDUJPOT

 5IF MJCSBSZ BMTP EFƶOFT UIF UZQFDMBTT CharParsing XIJDI


IBT Parsing BT B TVQFSDMBTT 5IJT IBOEMFT QBSTJOH JOEJWJE
VBM DIBSBDUFST

-- Text.Parser.Char
class Parsing m => CharParsing m where
$)"15&3  1"34&3 $0.#*/"5034 

8FƊWF BMSFBEZ TFFO char GSPN UIJT DMBTT CVU JU BMTP JODMVEFT
UIFTF

-- Parses any single character other than the


-- one provided. Returns the character parsed.
notChar :: Char -> m Char

-- Parser succeeds for any character.


-- Returns the character parsed.
anyChar :: m Char

-- Parses a sequence of characters, returns


-- the string parsed.
string :: String -> m String

-- Parses a sequence of characters represented


-- by a Text value, returns the parsed Text fragment.
text :: Text -> m Text

5IF 1BSTFST MJCSBSZ IBT NVDI NPSF UIBO UIJT CVU GPS PVS
JNNFEJBUF QVSQPTFT UIFTF XJMM TVƸDF 5IF JNQPSUBOU QPJOU JT
UIBU JU EFƶOFT GPS VT TPNF UZQFDMBTTFT BOE CBTJD DPNCJOBUPST
GPS DPNNPO QBSTJOH UBTLT 8F FODPVSBHF ZPV UP FYQMPSF UIF
EPDVNFOUBUJPO NPSF PO ZPVS PXO
$)"15&3  1"34&3 $0.#*/"5034 

 "MUFSOBUJWF
-FUƊT TBZ XF IBE B QBSTFS GPS OVNCFST BOE POF GPS BMQIBOV
NFSJD TUSJOHT

Prelude> import Text.Trifecta


Prelude> parseString (some letter) mempty "blah"
Success "blah"
Prelude> parseString integer mempty "123"
Success 123

8IBU JG XF IBE B UZQF UIBU DPVME CF BO JOUFHFS PS B TUSJOH


$)"15&3  1"34&3 $0.#*/"5034 

module AltParsing where

import Control.Applicative
import Text.Trifecta

type NumberOrString =
Either Integer String

a = "blah"
b = "123"
c = "123blah789"

parseNos :: Parser NumberOrString


parseNos =
(Left <$> integer)
<|> (Right <$> some letter)

main = do
print $ parseString (some letter) mempty a
print $ parseString integer mempty b
print $ parseString parseNos mempty a
print $ parseString parseNos mempty b
print $ parseString (many parseNos) mempty c
print $ parseString (some parseNos) mempty c
$)"15&3  1"34&3 $0.#*/"5034 

8F DBO SFBE <|> BT CFJOH BO ƌPSƍ PS EJTKVODUJPO PG PVS UXP


QBSTFST many JT ƌ[FSP PS NPSFƍ BOE some JT ƌPOF PS NPSFƍ

Prelude> parseString (some integer) mempty "123"


Success [123]
Prelude> parseString (many integer) mempty "123"
Success [123]
Prelude> parseString (many integer) mempty ""
Success []
Prelude> parseString (some integer) mempty ""
Failure (interactive):1:1: error: unexpected
EOF, expected: integer
<EOF>
^

8IBU XFƊSF UBLJOH BEWBOUBHF PG IFSF XJUI some many BOE


(<|>) JT UIF "MUFSOBUJWF UZQFDMBTT
$)"15&3  1"34&3 $0.#*/"5034 

class Applicative f => Alternative f where


-- | The identity of '<|>'
empty :: f a
-- | An associative binary operation
(<|>) :: f a -> f a -> f a

-- | One or more.
some :: f a -> f [a]
some v = some_v
where
many_v = some_v <|> pure []
some_v = (fmap (:) v) <*> many_v

-- | Zero or more.
many :: f a -> f [a]
many v = many_v
where
many_v = some_v <|> pure []
some_v = (fmap (:) v) <*> many_v

*G ZPV VTF UIF :info DPNNBOE JO UIF 3&1- BǒFS JNQPSUJOH


Text.Trifecta PS MPBEJOH UIF BCPWF NPEVMF ZPVƊMM ƶOE some
BOE many BSF EFƶOFE JO GHC.Base CFDBVTF UIFZ DPNF GSPN UIJT
UZQFDMBTT SBUIFS UIBO CFJOH TQFDJƶD UP B QBSUJDVMBS QBSTFS PS
UP UIF parsers MJCSBSZ 0S SFBMMZ FWFO B QBSUJDVMBS QSPCMFN
$)"15&3  1"34&3 $0.#*/"5034 

EPNBJO
8IBU JG XF XBOUFE UP SFRVJSF UIBU FBDI WBMVF CF TFQBSBUFE CZ
OFXMJOF 2VBTJ2VPUFT MFUT VT IBWF B NVMUJMJOF TUSJOH XJUIPVU
UIF OFXMJOF TFQBSBUPST BOE VTF JU BT B TJOHMF BSHVNFOU

{-# LANGUAGE QuasiQuotes #-}

module AltParsing where

import Control.Applicative
import Text.RawString.QQ
import Text.Trifecta

type NumberOrString =
Either Integer String

eitherOr :: String
eitherOr = [r|
123
abc
456
def
|]
$)"15&3  1"34&3 $0.#*/"5034 

2VBTJ2VPUFT
"CPWF UIF [r| JT CFHJOOJOH B RVBTJRVPUFE TFDUJPO VTJOH UIF
RVBTJRVPUFS OBNFE r /PUF XF IBE UP FOBCMF UIF 2VBTJ2VPUFT
MBOHVBHF FYUFOTJPO UP VTF UIJT TZOUBY "U UJNF PG XSJUJOH r JT
EFƶOFE JO raw-strings-qq WFSTJPO  BT GPMMPXT

r :: QuasiQuoter
r = QuasiQuoter {
-- Extracted from dead-simple-json.
quoteExp = return . LitE . StringL . normaliseNewlines,

-- error messages elided


quotePat = \_ -> fail "some error message"
quoteType = \_ -> fail "some error message"
quoteDec = \_ -> fail "some error message"

5IF JEFB IFSF JT UIBU UIJT JT B NBDSP UIBU MFUT VT XSJUF BS
CJUSBSZ UFYU JOTJEF PG UIF CMPDL UIBU CFHJOT XJUI [r| BOE FOET
XJUI |] 5IJT TQFDJƶD RVBTJRVPUFS FYJTUT UP NBLF JU NVDI OJDFS
BOE NPSF OBUVSBM UP XSJUF NVMUJMJOF TUSJOHT XJUIPVU NBOVBM
FTDBQJOH 5IF RVBTJRVPUFS JT HFOFSBUJOH UIF GPMMPXJOH GPS VT

5IFSFƊT B SBUIFS OJDF XJLJ QBHF BOE UVUPSJBM FYBNQMF BU https://wiki.haskell.org/
Quasiquotation
$)"15&3  1"34&3 $0.#*/"5034 

"\n\
\123\n\
\abc\n\
\456\n\
\def\n"

/PU BT OJDF SJHIU "T JU IBQQFOT JG ZPV XBOU UP TFF XIBU


B RVBTJRVPUFS PS UFNQMBUF IBTLFMM JT HFOFSBUJOH BU DPNQJMF
UJNF ZPV DBO FOBCMF UIF -ddump-splices ƷBH UP TFF XIBU JU EPFT
)FSFƊT BO FYBNQMF VTJOH B NJOJNBM TUVC ƶMF

{-# LANGUAGE QuasiQuotes #-}

module Quasimodo where

import Text.RawString.QQ

eitherOr :: String
eitherOr = [r|
123
abc
456
def
|]

https://wiki.haskell.org/Template_Haskell
$)"15&3  1"34&3 $0.#*/"5034 

5IFO JO ()$J XF VTF UIF :set DPNNBOE UP UVSO PO UIF


TQMJDF EVNQJOH ƷBH TP XF DBO TFF XIBU UIF RVBTJRVPUFS HFOFS
BUFE

Prelude> :set -ddump-splices


Prelude> :l code/quasi.hs
[1 of 1] Compiling Quasimodo
code/quasi.hs:(8,12)-(12,2): Splicing expression
"\n\
\123\n\
\abc\n\
\456\n"
======>
"\n\
\123\n\
\abc\n\
\456\n"

3JHIU TP CBDL UP UIF QBSTFS XF XFSF HPJOH UP XSJUF

3FUVSO UP "MUFSOBUJWF
"MM SJHIU XF SFUVSO OPX UP PVS "MU1BSTJOH NPEVMF 8FƊSF HPJOH
UP VTF UIJT GBOUBTUJD GVODUJPO
$)"15&3  1"34&3 $0.#*/"5034 

parseNos :: Parser NumberOrString


parseNos =
(Left <$> integer)
<|> (Right <$> some letter)

BOE SFXSJUF PVS main GVODUJPO UP BQQMZ UIBU UP UIF FJUIFS0S


WBMVF

main = do
print $ parseString parseNos mempty eitherOr

/PUF UIBU XF MJǒFE Left BOE Right PWFS UIFJS BSHVNFOUT


5IJT JT CFDBVTF UIFSF JT 1BSTFS TUSVDUVSF CFUXFFO UIF QPUFO
UJBM
WBMVF PCUBJOFE CZ SVOOJOH UIF QBSTFS BOE XIBU UIF EBUB
DPOTUSVDUPS FYQFDUT " WBMVF PG UZQF Parser Char JT B QBSTFS
UIBU XJMM QPTTJCMZ QSPEVDF B Char WBMVF JG JU JT HJWFO BO JOQVU UIBU
EPFTOƊU DBVTF JU UP GBJM 5IF UZQF PG some letter JT UIF GPMMPXJOH

Prelude> import Text.Trifecta


Prelude> :t some letter
some letter :: CharParsing f => f [Char]

)PXFWFS GPS PVS QVSQPTFT XF DBO KVTU TBZ UIBU UIF UZQF JT
TQFDJƶDBMMZ 5SJGFDUBƊT 1BSTFS UZQF

Prelude> let someLetter = some letter :: Parser [Char]


Prelude> let someLetter = some letter :: Parser String
$)"15&3  1"34&3 $0.#*/"5034 

*G XF USZ UP NBTI B EBUB DPOTUSVDUPS FYQFDUJOH B String BOE


PVS QBSTFSPGTUSJOH UPHFUIFS MJLF B LJE QMBZJOH XJUI BDUJPO
ƶHVSFT XF HFU B UZQF FSSPS

Prelude> data MyName = MyName String deriving Show


Prelude> MyName someLetter

Couldn't match type ‘Parser String’ with ‘[Char]’


Expected type: String
Actual type: Parser String
In the first argument of ‘MyName’, namely ‘someLetter’
In the expression: MyName someLetter

6OMFTT XF MJǒ JU PWFS UIF 1BSTFS TUSVDUVSF TJODF 1BSTFS JT B


'VODUPS

Prelude> :info Parser


{... content elided ...}
instance Monad Parser
instance Functor Parser
instance Applicative Parser
instance Monoid a => Monoid (Parser a)

instance Errable Parser


instance DeltaParsing Parser
instance TokenParsing Parser
instance Parsing Parser
$)"15&3  1"34&3 $0.#*/"5034 

instance CharParsing Parser

8F TIPVME KVTU OFFE BO fmap SJHIU

-- same deal
Prelude> :t MyName <$> someLetter
MyName <$> someLetter :: Parser MyName
Prelude> :t MyName `fmap` someLetter
MyName `fmap` someLetter :: Parser MyName

5IFO SVOOJOH FJUIFS PG UIFN

Prelude> parseString someLetter mempty "Chris"


Success "Chris"
Prelude> let mynameParser = MyName <$> someLetter
Prelude> parseString mynameParser mempty "Chris"
Success (MyName "Chris")

#SJMM
#BDL UP PVS PSJHJOBM DPEF XIJDI XJMM BDUVBMMZ TQJU PVU BO
FSSPS

Prelude> main
Failure (interactive):1:1: error: expected: integer,
letter

*UƊT FBTJFS UP TFF XIZ JG XF MPPL BU UIF UFTU TUSJOH


$)"15&3  1"34&3 $0.#*/"5034 

Prelude> eitherOr
"\n123\nabc\n456\ndef\n"

0OF XBZ UP ƶY UIJT JT UP BNFOE UIF RVBTJRVPUFE TUSJOH

eitherOr :: String
eitherOr = [r|123
abc
456
def
|]

8IBU JG XF BDUVBMMZ XBOUFE UP QFSNJU B OFXMJOF CFGPSF BU


UFNQUJOH UP QBSTF TUSJOHT PS JOUFHFST
$)"15&3  1"34&3 $0.#*/"5034 

eitherOr :: String
eitherOr = [r|
123
abc
456
def
|]

parseNos :: Parser NumberOrString


parseNos =
skipMany (oneOf "\n")
>>
(Left <$> integer)
<|> (Right <$> some letter)

main = do
print $ parseString parseNos mempty eitherOr

Prelude> main
Success (Left 123)

0, CVU XFƊE MJLF UP LFFQ QBSTJOH BǒFS FBDI MJOF *G XF USZ


UIF PCWJPVT UIJOH BOE VTF some UP BTL GPS POFPSNPSF SFTVMUT
XFƊMM HFU B TPNFXIBU NZTUFSJPVT FSSPS

Prelude> parseString (some parseNos) mempty eitherOr


$)"15&3  1"34&3 $0.#*/"5034 

Failure (interactive):6:1: error: unexpected


EOF, expected: integer, letter
<EOF>
^

5IF JTTVF IFSF JT UIBU XIJMF skipMany MFUT VT TLJQ [FSP PS


NPSF UJNFT JU NFBOT XF TUBSUFE UIF OFYU SVO PG UIF QBSTFS
CFGPSF XF IJU &0' 5IJT NFBOT JU FYQFDUT VT UP NBUDI BO JOUFHFS
PS TPNF MFUUFST BǒFS IBWJOH TFFO UIF OFXMJOF DIBSBDUFS BǒFS
ƌEFGƍ 8F DBO TJNQMZ BNFOE UIF JOQVU

eitherOr :: String
eitherOr = [r|
123
abc
456
def|]

0VS QSFWJPVT BUUFNQU XJMM OPX XPSL ƶOF

Prelude> parseString (some parseNos) mempty eitherOr


Success [Left 123,Right "abc",Left 456,Right "def"]

*G XFƊSF EJTTBUJTƶFE XJUI TJNQMZ DIBOHJOH UIF SVMFT PG UIF


HBNF UIFSF BSF B DPVQMF XBZT XF DBO NBLF PVS QBSTFS DPQF
XJUI TQVSJPVT UFSNJOBM OFXMJOFT 0OF JT UP BEE BOPUIFS skipMany
SVMF BǒFS XF QBSTF PVS WBMVF
$)"15&3  1"34&3 $0.#*/"5034 

parseNos :: Parser NumberOrString


parseNos = do
skipMany (oneOf "\n")
v <- (Left <$> integer) <|> (Right <$> some letter)
skipMany (oneOf "\n")
return v

"OPUIFS PQUJPO JT UP LFFQ UIF QSFWJPVT WFSTJPO PG UIF QBSTFS


XIJDI TLJQT B QPUFOUJBM MFBEJOH OFXMJOF

parseNos :: Parser NumberOrString


parseNos =
skipMany (oneOf "\n")
>>
(Left <$> integer)
<|> (Right <$> some letter)

#VU UIFO UPLFOJ[F JU XJUI UIF EFGBVMU token CFIBWJPS

Prelude> parseString (some (token parseNos)) mempty eitherOr


Success [Left 123,Right "abc",Left 456,Right "def"]

8FƊMM FYQMBJO TPPO XIBU UIJT UPLFO TUVƵ JT BCPVU CVU XF


XBOU UP CF B CJU DBSFGVM IFSF BT UPLFO QBSTFST BOE DIBSBDUFS
QBSTFST BSF EJƵFSFOU TPSUT PG UIJOHT 8IBU BQQMZJOH token UP
parseNos EJE GPS VT IFSF JT NBLF JU PQUJPOBMMZ DPOTVNF USBJMJOH
XIJUFTQBDF XF EPOƊU DBSF BCPVU XIFSF XIJUFTQBDF JODMVEFT
OFXMJOF DIBSBDUFST
$)"15&3  1"34&3 $0.#*/"5034 

&YFSDJTF 5SZ 5SZ


.BLF B QBSTFS VTJOH UIF FYJTUJOH GSBDUJPO QBSTFS QMVT B OFX EFD
JNBM QBSTFS UIBU DBO QBSTF FJUIFS EFDJNBMT PS GSBDUJPOT :PVƊMM
XBOU UP VTF <|> GSPN "MUFSOBUJWF UP DPNCJOF UIFƒBMUFSOBUJWF
QBSTFST *G ZPV ƶOE UIJT UPP EJƸDVMU XSJUF B QBSTFS UIBU QBSTFT
TUSBJHIUGPSXBSE JOUFHFST PS GSBDUJPOT .BLF B EBUBUZQF UIBU DPO
UBJOT FJUIFS BO JOUFHFS PS B SBUJPOBM BOE VTF UIBU EBUBUZQF BT
UIF SFTVMU PG UIF QBSTFS 0S VTF &JUIFS 3VO GSFF HSBTTIPQQFS
)JOU XFƊWF OPU FYQMBJOFE JU ZFU CVU ZPV NBZ XBOU UP USZ
try

 1BSTJOH DPOƶHVSBUJPO ƶMFT


'PS PVS OFYU FYBNQMFT XFƊMM CF VTJOH UIF */* DPOƶHVSBUJPO
ƶMF GPSNBU QBSUMZ CFDBVTF JUƊT BO JOGPSNBM TUBOEBSE TP XF DBO
QMBZ GBTU BOE MPPTF GPS MFBSOJOH BOE FYQFSJNFOUBUJPO QVSQPTFT
8FƊSF BMTP VTJOH */* CFDBVTF JUƊT SFMBUJWFMZ VODPNQMJDBUFE
)FSFƊT B UFFOTZ FYBNQMF PG BO */* DPOƶH ƶMF

; comment
[section]
host=wikipedia.org
alias=claw

https://en.wikipedia.org/wiki/INI_file
$)"15&3  1"34&3 $0.#*/"5034 

5IF BCPWF DPOUBJOT B DPNNFOU XIJDI DPOUSJCVUFT OPUI


JOH UP UIF EBUB QBSTFE PVU PG UIF DPOƶHVSBUJPO ƶMF CVU XIJDI
NBZ QSPWJEF DPOUFYU UP UIF TFUUJOHT CFJOH DPOƶHVSFE *UƊT GPM
MPXFE CZ B TFDUJPO IFBEFS OBNFE "section" XIJDI DPOUBJOT
UXP TFUUJOHT POF OBNFE "host" XJUI UIF WBMVF "wikipedia.org"
BOPUIFS OBNFE "alias" XJUI UIF WBMVF "claw"
8FƊMM CFHJO UIJT FYBNQMF XJUI PVS QSBHNBT NPEVMF EFDMB
SBUJPO BOE JNQPSUT

{-# LANGUAGE OverloadedStrings #-}


{-# LANGUAGE QuasiQuotes #-}

module Data.Ini where

import Control.Applicative
import Data.ByteString (ByteString)
import Data.Char (isAlpha)
import Data.Map (Map)
import qualified Data.Map as M
import Data.Text (Text)
import qualified Data.Text.IO as TIO
import Test.Hspec
import Text.RawString.QQ
-- parsers 0.12.3, trifecta 1.5.2
import Text.Trifecta
$)"15&3  1"34&3 $0.#*/"5034 

0WFSMPBEFE4USJOHT BOE 2VBTJ2VPUFT TIPVME CF GBNJMJBS CZ


OPX
8IFO XSJUJOH QBSTFST JO )BTLFMM JUƊT PǒFO FBTJFTU UP XPSL
JO UFSNT PG TNBMMFS QBSTFST UIBU EFBM XJUI B TVCQSPCMFN PG
UIF PWFSBMM QBSTJOH QSPCMFN ZPVƊSF TPMWJOH UIFO DPNCJOJOH
UIFN JOUP UIF ƶOBM QBSTFS 5IJT JTOƊU B QFSGFDU SFDJQF GPS VO
EFSTUBOEJOH ZPVS QBSTFS CVU CFJOH BCMF UP DPNQPTF UIFN
TUSBJHIUGPSXBSEMZ MJLF GVODUJPOT JT QSFUUZ EBOH OJǒZ 4P TUBSU
JOH XJUI B TJNQMF QSPCMFN MFUƊT DSFBUF B UFTU JOQVU GPS BO */*
IFBEFS B EBUBUZQF BOE UIFO UIF QBSTFS GPS JU
$)"15&3  1"34&3 $0.#*/"5034 

headerEx :: ByteString
headerEx = "[blah]"

-- "[blah]" -> Section "blah"


newtype Header =
Header String
deriving (Eq, Ord, Show)

parseBracketPair :: Parser a -> Parser a


parseBracketPair p = char '[' *> p <* char ']'
-- these operators mean the brackets will be
-- parsed and then discarded
-- but the p will remain as our result

parseHeader :: Parser Header


parseHeader =
parseBracketPair (Header <$> some letter)

)FSF XFƊWF BDUVBMMZ DPNCJOFE UXP QBSTFST JO PSEFS UP QBSTF


B )FBEFS 8F DBO FYQFSJNFOU XJUI FBDI PG UIFN JO UIF 3&1-
'JSTU XFƊMM FYBNJOF UIF UZQFT PG UIF some letter QBSTFS XF QBTTFE
UP parseBracketPair

Prelude> :t some letter


some letter :: CharParsing f => f [Char]
Prelude> :t Header <$> some letter
$)"15&3  1"34&3 $0.#*/"5034 

Header <$> some letter :: CharParsing f => f Header


Prelude> let slp = Header <$> some letter :: Parser Header

5IF ƶSTU UZQF JT TPNF QBSTFS UIBU DBO VOEFSTUBOE DIBSBDUFST


XIJDI XJMM QSPEVDF B 4USJOH WBMVF JG JU TVDDFFET 5IF TFDPOE
UZQF JT UIF TBNF CVU QSPEVDFT B Header WBMVF JOTUFBE PG B 4USJOH
1BSTFS UZQFT JO )BTLFMM BMNPTU BMXBZT FODPEF UIF QPTTJCJMJUZ
PG GBJMVSF XFƊMM DPWFS IPX MBUFS JO UIJT DIBQUFS 5IF UIJSE UZQF
HJWFT VT DPODSFUF 1BSTFS UZQF GSPN 5SJGFDUB XIFSF UIFSF IBE
CFFO UIF QPMZNPSQIJD UZQF ԕ
5IF letter GVODUJPO QBSTFT B TJOHMF DIBSBDUFS XIJMF some
letter QBSTFT POF PS NPSF DIBSBDUFST 8F OFFE UP XSBQ UIF
)FBEFS DPOTUSVDUPS BSPVOE UIBU TP UIBU PVS SFTVMU UIFSF ƈ
XIBUFWFS MFUUFST NJHIU CF JOTJEF UIF CSBDLFUT UIF ԟ PG parseBracketPai
ƈ XJMM CF MBCFMFE BT UIF )FBEFS PG UIF ƶMF JO UIF ƶOBM QBSTF
/FYU assignmentEx JT KVTU TPNF UFTU JOQVU TP XF DBO CFHJO
LJDLJOH BSPVOE PVS QBSTFS 5IF UZQF TZOPOZNT BSF KVTU UP
NBLF UIF UZQFT NPSF SFBEBCMF BT XFMM /PUIJOH UPP TQFDJBM
IFSF
$)"15&3  1"34&3 $0.#*/"5034 

assignmentEx :: ByteString
assignmentEx = "woot=1"

type Name = String


type Value = String
type Assignments = Map Name Value

parseAssignment :: Parser (Name, Value)


parseAssignment = do
name <- some letter
_ <- char '='
val <- some (noneOf "\n")
skipEOL -- important!
return (name, val)

-- | Skip end of line and whitespace beyond.


skipEOL :: Parser ()
skipEOL = skipMany (oneOf "\n")

-FU VT FYQMBJO parseAssignment TUFQ CZ TUFQ 'PS QBSTJOH UIF


JOJUJBM LFZ PS OBNF PG BO BTTJHONFOU XF QBSTF POF PS NPSF
MFUUFST

name <- some letter


$)"15&3  1"34&3 $0.#*/"5034 

5IFO XF QBSTF BOE UISPX BXBZ UIF ƌƍ VTFE UP TFQBSBUF LFZT
BOE WBMVFT

_ <- char '='

5IFO XF QBSTF POF PS NPSF DIBSBDUFST BT MPOH BT UIFZ BSFOƊU


B OFXMJOF 5IJT JT TP MFUUFST OVNCFST BOE XIJUFTQBDF BSF
QFSNJUUFE

val <- some (noneOf "\n")

8F TLJQ ƌFOEPGMJOFƍ VOUJM XF TUPQ HFUUJOH OFXMJOF DIBSBD


UFST

skipEOL -- important!

5IJT JT TP XF DBO EFMJOFBUF UIF FOE PG BTTJHONFOUT BOE


QBSTF NPSF UIBO POF BTTJHONFOU JO B TUSBJHIUGPSXBSE NBOOFS
$POTJEFS BO BMUFSOBUJWF WBSJBOU PG UIJT TBNF QBSTFS UIBU EPFTOƊU
IBWF skipEOL

parseAssignment' :: Parser (Name, Value)


parseAssignment' = do
name <- some letter
_ <- char '='
val <- some (noneOf "\n")
return (name, val)
$)"15&3  1"34&3 $0.#*/"5034 

5IFO USZJOH PVU UIJT WBSJBOU PG UIF QBSTFS

Prelude> let spa' = some parseAssignment'


Prelude> let s = "key=value\nblah=123"
Prelude> parseString spa' mempty s
Success [("key","value")]

1JUZ $BOƊU QBSTF UIF TFDPOE BTTJHONFOU #VU UIF ƶSTU WFS
TJPO UIBU JODMVEFT UIF skipEOL TIPVME XPSL

Prelude> let spa = some parseAssignment


Prelude> parseString spa mempty s
Success [("key","value"),("blah","123")]
Prelude> let d = "key=value\n\n\ntest=data"
Prelude> parseString spa mempty d
Success [("key","value"),("test","data")]

8F IBWF UP TLJQ UIF POFPSNPSF OFXMJOF DIBSBDUFST TFQB


SBUJOH UIF ƶSTU BOE TFDPOE BTTJHONFOU JO PSEFS GPS UIF SFSVO
PG UIF BTTJHONFOU QBSTFS UP CFHJO TVDDFTTGVMMZ QBSTJOH UIF
MFUUFST UIBU NBLF VQ UIF LFZ PG UIF TFDPOE BTTJHONFOU )BQQZ
NBLJOH SJHIU
8F ƶOJTI UIJOHT PƵ GPS parseAssignment CZ UVQMJOH OBNF BOE
WBMVF UPHFUIFS BOE SFFNCFEEJOH UIF SFTVMU JO UIF Parser UZQF

return (name, val)


$)"15&3  1"34&3 $0.#*/"5034 

5IFO GPS EFBMJOH XJUI */* DPNNFOUT XIFSF ƌEFBMJOH XJUIƍ


NFBOT TLJQQJOH UIFN JO UIF QBSTFS BOE EJTDBSEJOH UIF EBUB

commentEx :: ByteString
commentEx =
"; last modified 1 April\
\ 2001 by John Doe"

commentEx' :: ByteString
commentEx' =
"; blah\n; woot\n \n;hah"

-- | Skip comments starting at the


-- beginning of the line.
skipComments :: Parser ()
skipComments =
skipMany (do _ <- char ';' <|> char '#'
skipMany (noneOf "\n")
skipEOL)

8F NBEF B DPVQMF PG DPNNFOU FYBNQMFT GPS UFTUJOH UIF


QBSTFS /PUF UIBU DPNNFOUT DBO CFHJO XJUI # PS ;
/FYU XF OFFE TFDUJPO QBSTJOH 8FƊMM NBLF TPNF EBUB GPS
UFTUJOH UIBU PVU KVTU BT XF EJE XJUI DPNNFOUT BCPWF 5IJT JT
BMTP XIFSF XFƊMM QVU UIBU 2VBTJ2VPUFT QSBHNB UP VTF BMMPXJOH
VT UP NBLF NVMUJMJOF TUSJOHT OJDFS UP XSJUF
$)"15&3  1"34&3 $0.#*/"5034 

sectionEx :: ByteString
sectionEx =
"; ignore me\n[states]\nChris=Texas"

sectionEx' :: ByteString
sectionEx' = [r|
; ignore me
[states]
Chris=Texas
|]

sectionEx'' :: ByteString
sectionEx'' = [r|
; comment
[section]
host=wikipedia.org
alias=claw

[whatisit]
red=intoothandclaw
|]

5IFO HFUUJOH PO UP UIF TFDUJPO QBSTJOH QSPQFS


$)"15&3  1"34&3 $0.#*/"5034 

data Section =
Section Header Assignments
deriving (Eq, Show)

newtype Config =
Config (Map Header Assignments)
deriving (Eq, Show)

skipWhitespace :: Parser ()
skipWhitespace =
skipMany (char ' ' <|> char '\n')

parseSection :: Parser Section


parseSection = do
skipWhitespace
skipComments
h <- parseHeader
skipEOL
assignments <- some parseAssignment
return $
Section h (M.fromList assignments)

"CPWF XF EFƶOFE EBUBUZQFT GPS B TFDUJPO BOE BO FOUJSF */*


DPOƶH :PVƊMM OPUJDF UIBU parseSection TLJQT CPUI XIJUFTQBDF
BOE DPNNFOUT OPX "OE JU SFUVSOT UIF QBSTFE TFDUJPO XJUI
$)"15&3  1"34&3 $0.#*/"5034 

UIF IFBEFS UIBUƊT UIF ԗ


BOE B NBQ PG BTTJHONFOUT

*Data.Ini> parseByteString parseSection mempty sectionEx


Success (Section (Header "states") (fromList [("Chris","Texas")]))

4P GBS TP HPPE /FYU MFUƊT SPMM UIF TFDUJPOT VQ JOUP B Map


UIBU LFZT TFDUJPO EBUB CZ TFDUJPO OBNF XJUI UIF WBMVFT CFJOH
GVSUIFS NPSF .BQT PG BTTJHONFOU OBNFT NBQQFE UP UIFJS
WBMVFT 8F VTF foldr UP BHHSFHBUF UIF MJTU PG TFDUJPOT JOUP B
TJOHMF .BQ WBMVF

rollup :: Section
-> Map Header Assignments
-> Map Header Assignments
rollup (Section h a) m =
M.insert h a m

parseIni :: Parser Config


parseIni = do
sections <- some parseSection
let mapOfSections =
foldr rollup M.empty sections
return (Config mapOfSections)

"ǒFS ZPV MPBE UIJT DPEF JOUP ZPVS 3&1- USZ SVOOJOH

parseByteString parseIni mempty sectionEx


$)"15&3  1"34&3 $0.#*/"5034 

BOE DPNQBSJOH JU UP UIF PVUQVU PG

parseByteString parseSection mempty sectionEx

UIBU ZPV TBX BCPWF


/PX XFƊMM QVU UPHFUIFS PVS main GVODUJPO )FSF XFƊSF JOUFS
FTUFE JO XIFUIFS PVS QBSTFST EP XIBU UIFZ TIPVME EP SBUIFS
UIBO QBSTJOH BO BDUVBM */* ƶMF TP XFƊMM IBWF UIF main GVODUJPO
SVO TPNF hspec UFTUT 8FƊMM VTF B IFMQFS GVODUJPO maybeSuccess
BT QBSU PG UIF UFTUT

maybeSuccess :: Result a -> Maybe a


maybeSuccess (Success a) = Just a
maybeSuccess _ = Nothing

main :: IO ()
main = hspec $ do

describe "Assignment Parsing" $


it "can parse a simple assignment" $ do
let m = parseByteString parseAssignment
mempty assignmentEx
r' = maybeSuccess m
print m
r' `shouldBe` Just ("woot", "1")
$)"15&3  1"34&3 $0.#*/"5034 

describe "Header Parsing" $


it "can parse a simple header" $ do
let m = parseByteString parseHeader mempty headerEx
r' = maybeSuccess m
print m
r' `shouldBe` Just (Header "blah")

describe "Comment parsing" $


it "Can skip a comment before a header" $ do
let p = skipComments >> parseHeader
i = "; woot\n[blah]"
m = parseByteString p mempty i
r' = maybeSuccess m
print m
r' `shouldBe` Just (Header "blah")
$)"15&3  1"34&3 $0.#*/"5034 

describe "Section parsing" $


it "Can parse a simple section" $ do
let m = parseByteString parseSection
mempty sectionEx
r' = maybeSuccess m
states = M.fromList [("Chris", "Texas")]
expected' = Just (Section
(Header "states")
states)
print m
r' `shouldBe` expected'
$)"15&3  1"34&3 $0.#*/"5034 

describe "INI parsing" $


it "Can parse multiple sections" $ do
let m = parseByteString parseIni mempty sectionEx''
r' = maybeSuccess m
sectionValues = M.fromList
[ ("alias", "claw")
, ("host", "wikipedia.org")]
whatisitValues = M.fromList
[("red", "intoothandclaw")]
expected' = Just (Config
(M.fromList
[ (Header "section"
, sectionValues)
, (Header "whatisit"
, whatisitValues)]))
print m
r' `shouldBe` expected'

8F MFBWF JU UP ZPV UP SVO UIJT BOE FYQFSJNFOU XJUI JU

 $IBSBDUFS BOE UPLFO QBSTFST


"MM SJHIU UIBU XBT B MPU PG DPEF -FUƊT BMM TUFQ CBDL BOE UBLF B
EFFQ CSFBUI
$)"15&3  1"34&3 $0.#*/"5034 

:PV QSPCBCMZ IBWF TPNF JEFB CZ OPX PG XIBU XF NFBO CZ


UPLFOJ[JOH CVU UIF UJNF IBT DPNF GPS NPSF EFUBJM 5PLFOJ[B
UJPO JT B IBOEZ QBSTJOH UBDUJD TP JUƊT CBLFE JOUP TPNF PG UIF
MJCSBSZ GVODUJPOT XFƊWF CFFO VTJOH *UƊT XPSUI EJWJOH JO BOE
FYQMPSJOH XIBU JU NFBOT
5SBEJUJPOBMMZ QBSTJOH IBT CFFO EPOF JO UXP TUBHFT MFYJOH
BOE QBSTJOH $IBSBDUFST GSPN B TUSFBN XJMM CF GFE JOUP UIF
MFYFS XIJDI XJMM UIFO FNJU UPLFOT PO EFNBOE UP UIF QBSTFS
VOUJM JU IBT OP NPSF UP FNJU 5IF QBSTFS UIFO TUSVDUVSFT UIF
TUSFBN PG UPLFOT JOUP B USFF DPNNPOMZ DBMMFE BO ƌBCTUSBDU
TZOUBY USFFƍ PS "45

-- hand-wavy types, ``Stream'' because


-- production-grade parsers in Haskell
-- won't use [] for performance reasons
lexer :: Stream Char -> Stream Token
parser :: Stream Token -> AST

-FYFST BSF TJNQMFS UZQJDBMMZ QFSGPSNJOH QBSTFT UIBU EPOƊU


SFRVJSF MPPLJOH BIFBE JOUP UIF JOQVU TUSFBN CZ NPSF UIBO
POF DIBSBDUFS PS UPLFO BU B UJNF -FYFST BSF BU UJNFT DBMMFE
UPLFOJ[FST -FYJOH JT TPNFUJNFT EPOF XJUI SFHVMBS FYQSFTTJPOT
CVU B QBSTJOH MJCSBSZ JO )BTLFMM XJMM VTVBMMZ JOUFOE UIBU ZPV
EP ZPVS MFYJOH BOE QBSTJOH XJUI UIF TBNF "1* -FYFST PS
UPLFOJ[FST
BOE QBSTFST IBWF B MPU JO DPNNPO CFJOH QSJNBSJMZ
$)"15&3  1"34&3 $0.#*/"5034 

EJƵFSFOUJBUFE CZ UIFJS QVSQPTF BOE DMBTT PG HSBNNBS 

*OTFSU UPLFOT UP QMBZ


-FUƊT QMBZ BSPVOE XJUI TPNF UIJOHT UP TFF XIBU UPLFOJ[JOH
EPFT GPS VT

Prelude> parseString (some digit) mempty "123 456"


Success "123"
Prelude> parseString (some (some digit)) mempty "123 456"
Success ["123"]

Prelude> parseString (some integer) mempty "123"


Success [123]
Prelude> parseString (some integer) mempty "123456"
Success [123456]

5IF QSPCMFN IFSF JT UIBU JG XF XBOUFE UP SFDPHOJ[F  BOE


 BT JOEFQFOEFOU TUSJOHT XF OFFE TPNF LJOE PG TFQBSBUPS
/PX XF DBO HP BIFBE BOE EP UIBU NBOVBMMZ CVU UIF UPLFOJ[FST
JO parsers DBO EP JU GPS ZPV UPP BMTP IBOEMJOH B NJYUVSF PG
XIJUFTQBDF BOE OFXMJOFT

Prelude> parseString (some integer) mempty "123 456"


Success [123,456]
Prelude> parseString (some integer) mempty "123\n\n 456"
Success [123,456]

https://en.wikipedia.org/wiki/Chomsky_hierarchy
$)"15&3  1"34&3 $0.#*/"5034 

0S FWFO TQBDF BOE OFXMJOFT JOUFSMFBWFE

Prelude> parseString (some integer) mempty "123 \n \n 456"


Success [123,456]

#VU TJNQMZ BQQMZJOH UPLFO UP digit EPFTOƊU EP XIBU ZPV


UIJOL

Prelude> parseString (token (some digit)) mempty "123 \n \n 456"


Success "123"
Prelude> parseString (token (some (token digit))) mempty "123 \n \n
Success "123456"

Prelude> parseString (some decimal) mempty "123 \n \n 456"


Success [123]
Prelude> parseString (some (token decimal)) mempty "123 \n \n 456"
Success [123,456]

$PNQBSF UIBU UP UIF integer GVODUJPO XIJDI JT BMSFBEZ B


UPLFOJ[FS

Prelude> parseString (some integer) mempty "1\n2\n 3\n"


Success [1,2,3]

8F DBO XSJUF B UPLFOJ[JOH QBSTFS MJLF some integer MJLF UIJT

p' :: Parser [Integer]


p' = some $ do
i <- token (some digit)
return (read i)
$)"15&3  1"34&3 $0.#*/"5034 

"OE XF DBO DPNQBSF UIF PVUQVU PG UIBU UP UIF PVUQVU PG


BQQMZJOH token UP digit

Prelude> parseString p' mempty "1\n2\n3"


Success [1,2,3]
Prelude> parseString (token (some digit)) mempty "1\n2\n3"
Success "1"
Prelude> parseString (some (token (some digit))) mempty "1\n2\n3"
Success ["1","2","3"]

:PVƊMM XBOU UP UIJOL DBSFGVMMZ BCPVU UIF TDPQF BU XIJDI


ZPVƊSF UPLFOJ[JOH BT XFMM

Prelude> let tknWhole = token $ char 'a' >> char 'b'


Prelude> parseString tknWhole mempty "a b"
Failure (interactive):1:2: error: expected: "b"
a b<EOF>
^
Prelude> parseString tknWhole mempty "ab ab"
Success 'b'
Prelude> parseString (some tknWhole) mempty "ab ab"
Success "bb"

*G XF XBOUFE UIBU ƶSTU FYBNQMF UP XPSL XF OFFE UP UPLFOJ[F


UIF QBSTF PG UIF ƶSTU DIBSBDUFS OPU UIF XIPMF BUIFOC QBSTF

Prelude> let tknCharA = (token (char 'a')) >> char 'b'


$)"15&3  1"34&3 $0.#*/"5034 

Prelude> parseString tknCharA mempty "a b"


Success 'b'
Prelude> parseString (some tknCharA) mempty "a ba b"
Success "bb"
Prelude> parseString (some tknCharA) mempty "a b a b"
Success "b"

5IF MBTU FYBNQMF TUPQT BU UIF ƶSTU Ԑ ԑ QBSTF CFDBVTF UIF


QBSTFS EPFTOƊU TBZ BOZUIJOH BCPVU B TQBDF BǒFS ԑ BOE UIF UPL
FOJ[BUJPO CFIBWJPS POMZ BQQMJFT UP XIBU GPMMPXFE Ԑ 8F DBO
UPLFOJ[F CPUI DIBSBDUFS QBSTFST UIPVHI

Prelude> let tknBoth = token (char 'a') >> token (char 'b')
Prelude> parseString (some tknBoth) mempty "a b a b"
Success "bb"

" NJME XBSOJOH EPOƊU HFU UPP UPLFOJ[BUJPO IBQQZ 5SZ UP


NBLF JU DPBSTFHSBJOFE BOE TFMFDUJWF 0WFSVTF PG UPLFOJ[JOH
QBSTFST PS NJYUVSF UIFSFPG XJUI DIBSBDUFS QBSTFST DBO NBLF
ZPVS QBSTFS TMPX PS IBSE UP VOEFSTUBOE 6TF ZPVS KVEHNFOU
,FFQ JO NJOE UIBU UPLFOJ[BUJPO JTOƊU FYDMVTJWFMZ BCPVU XIJUFT
QBDF JUƊT BCPVU JHOPSJOH OPJTF TP ZPV DBO GPDVT PO UIF TUSVD
UVSFT ZPV BSF QBSTJOH
$)"15&3  1"34&3 $0.#*/"5034 

 1PMZNPSQIJD QBSTFST


*G XF UBLF UIF UJNF UP BTTFSU QPMZNPSQIJD UZQFT GPS PVS QBSTFST
XF DBO HFU QBSTFST UIBU DBO CF SVO VTJOH attoparsec trifecta
parsec PS BOZUIJOH FMTF UIBU IBT JNQMFNFOUFE UIF OFDFTTBSZ
UZQFDMBTTFT -FUƊT HJWF JU B XIJSM TIBMM XF

{-# LANGUAGE OverloadedStrings #-}

module Text.Fractions where

import Control.Applicative
import Data.Attoparsec.Text (parseOnly)
import Data.Ratio ((%))
import Data.String (IsString)
import Text.Trifecta
$)"15&3  1"34&3 $0.#*/"5034 

badFraction :: IsString s => s


badFraction = "1/0"

alsoBad :: IsString s => s


alsoBad = "10"

shouldWork :: IsString s => s


shouldWork = "1/2"

shouldAlsoWork :: IsString s => s


shouldAlsoWork = "2/1"

parseFraction :: (Monad m, TokenParsing m) => m Rational


parseFraction = do
numerator <- decimal
_ <- char '/'
denominator <- decimal
case denominator of
0 -> fail "Denominator cannot be zero"
_ -> return (numerator % denominator)

8FƊWF MFǒ TPNF UZQFDMBTTDPOTUSBJOFE QPMZNPSQIJTN JO


PVS UZQF TJHOBUVSFT GPS ƷFYJCJMJUZ 8FƊMM XSJUF B main GVODUJPO
UIBU XJMM SVO CPUI attoparsec BOE trifecta WFSTJPOT GPS VT TP XF
DBO DPNQBSF UIF PVUQVUT EJSFDUMZ
$)"15&3  1"34&3 $0.#*/"5034 

main :: IO ()
main = do
-- parseOnly is Attoparsec
print $ parseOnly parseFraction badFraction
print $ parseOnly parseFraction shouldWork
print $ parseOnly parseFraction shouldAlsoWork
print $ parseOnly parseFraction alsoBad

-- parseString is Trifecta
print $ parseString parseFraction mempty badFraction
print $ parseString parseFraction mempty shouldWork
print $ parseString parseFraction mempty shouldAlsoWork
print $ parseString parseFraction mempty alsoBad

Prelude> main
Left "Failed reading: Denominator cannot be zero"
Right (1 % 2)
Right (2 % 1)
Left "\"/\": not enough input"
Failure (interactive):1:4: error: Denominator
cannot be zero, expected: digit
1/0<EOF>
^
Success (1 % 2)
Success (2 % 1)
Failure (interactive):1:3: error: unexpected
$)"15&3  1"34&3 $0.#*/"5034 

EOF, expected: "/", digit


10<EOF>
^

4FF XIBU XF NFBOU FBSMJFS BCPVU UIF FSSPS NFTTBHFT

*UƊT OPU QFSGFDU BOE DPVME CJUF ZPV


8IJMF UIF QPMZNPSQIJD QBSTFS DPNCJOBUPST JO UIF parsers MJ
CSBSZ FOBCMF ZPV UP XSJUF QBSTFST XIJDI DBO UIFO CF SVO XJUI
WBSJPVT QBSTJOH MJCSBSJFT UIJT EPFTOƊU GSFF ZPV PG VOEFSTUBOE
JOH UIF QBSUJDVMBSJUJFT PG FBDI *O HFOFSBM 5SJGFDUB USJFT UP
NBUDI 1BSTFDƊT CFIBWJPST JO NPTU SFTQFDUT UIF MBUUFS PG XIJDI
JT NPSF FYUFOTJWFMZ EPDVNFOUFE

'BJMVSF BOE CBDLUSBDLJOH


3FUVSOJOH UP PVS DVSTPS NPEFM PG QBSTFST CBDLUSBDLJOH JT
SFUVSOJOH UIF DVSTPS UP XIFSF JU XBT CFGPSF B GBJMJOH QBSTFS
DPOTVNFE JOQVU *O TPNF DBTFT JU DBO CF B MJUUMF DPOGVTJOH
UP EFCVH UIF TBNF FSSPS JO UXP EJƵFSFOU SVOT PG UIF TBNF
QBSTFS EPJOH FTTFOUJBMMZ UIF TBNF UIJOHT JO 5SJGFDUB 1BSTFD
BOE "UUPQBSTFD CVU UIF FSSPST UIFNTFMWFT NJHIU CF EJƵFSFOU
-FUT DPOTJEFS BO FYBNQMF PG UIJT

{-# LANGUAGE OverloadedStrings #-}


$)"15&3  1"34&3 $0.#*/"5034 

8F VTF OverloadedStrings TP UIBU XF DBO VTF TUSJOH MJUFSBMT BT


JG UIFZ XFSF CZUFTUSJOHT XIFO UFTUJOH "UUPQBSTFD

module BT where

import Control.Applicative
import qualified Data.Attoparsec.ByteString
as A
import Data.Attoparsec.ByteString (parseOnly)
import Data.ByteString (ByteString)
import Text.Trifecta hiding (parseTest)
import Text.Parsec (Parsec, parseTest)

trifP :: Show a
=> Parser a
-> String -> IO ()
trifP p i =
print $ parseString p mempty i

)FMQFS GVODUJPO UP SVO B 5SJGFDUB QBSTFS BOE QSJOU UIF SFTVMU

parsecP :: (Show a)
=> Parsec String () a
-> String -> IO ()
parsecP = parseTest

)FMQFS GVODUJPO UP SVO B 1BSTFD QBSTFS BOE QSJOU UIF SFTVMU


$)"15&3  1"34&3 $0.#*/"5034 

attoP :: Show a
=> A.Parser a
-> ByteString -> IO ()
attoP p i =
print $ parseOnly p i

)FMQFS GVODUJPO GPS "UUPQBSTFD 4BNF EFBM BT CFGPSF

nobackParse :: (Monad f, CharParsing f)


=> f Char
nobackParse =
(char '1' >> char '2')
<|> char '3'

)FSFƊT PVS ƶSTU QBSTFS *U BUUFNQUT UP QBSTF '1' GPMMPXFE CZ


'2' PS '3' 5IJT QBSTFS EPFT OPU CBDLUSBDL

tryParse :: (Monad f, CharParsing f)


=> f Char
tryParse =
try (char '1' >> char '2')
<|> char '3'

5IJT QBSTFS IBT TJNJMBS CFIBWJPS UP UIF QSFWJPVT POF FYDFQU


JU CBDLUSBDLT JG UIF ƶSTU QBSTF GBJMT 8IBU CBDLUSBDLJOH NFBOT
IFSF JT UIBU UIF JOQVU DVSTPS SFUVSOT UP XIFSF JU XBT CFGPSF UIF
GBJMFE QBSTFS DPOTVNFE JOQVU
$)"15&3  1"34&3 $0.#*/"5034 

main :: IO ()
main = do
-- trifecta
trifP nobackParse "13"
trifP tryParse "13"
-- parsec
parsecP nobackParse "13"
parsecP tryParse "13"
-- attoparsec
attoP nobackParse "13"
attoP tryParse "13"

5IF FSSPS NFTTBHFT ZPV HFU GSPN FBDI QBSTFS BSF HPJOH
UP WBSZ B CJU 5IJT JTOƊU CFDBVTF UIFZƊSF XJMEMZ EJƵFSFOU CVU
SBUIFS NPTUMZ CFDBVTF IPX UIFZ BUUSJCVUF FSSPST JT EJƵFSFOU
:PV TIPVME TFF TPNFUIJOH MJLF

Prelude> main
Failure (interactive):1:2:
error: expected: "2"
13<EOF>
^
Failure (interactive):1:1: error:
expected: "3"
13<EOF>
^
$)"15&3  1"34&3 $0.#*/"5034 

parse error at (line 1, column 2):


unexpected "3"
expecting "2"
parse error at (line 1, column 2):
unexpected "3"
expecting "2"
Left "\"3\": satisfyElem"
Left "\"3\": satisfyElem"

$POWFSTFMZ JG ZPV USZ UIF WBMJE JOQVUT "12" BOE "3" XJUI
nobackParse BOE FBDI PG UIF UISFF QBSTFST ZPV TIPVME TFF BMM PG
UIFN TVDDFFE
5IJT DBO CF WFSZ DPOGVTJOH BT XIFO ZPV BEE CBDLUSBDLJOH
UP B QBSTFS FSSPS BUUSJCVUJPO DBO CFDPNF B MJUUMF NPSF DPNQMJ
DBUFE BU UJNFT 5P BWPJE UIJT DPOTJEFS VTJOH UIF <?> PQFSBUPS
UP BOOPUBUF QBSTF SVMFT BOZ UJNF ZPV VTF try

tryAnnot :: (Monad f, CharParsing f)


=> f Char
tryAnnot =
(try (char '1' >> char '2')
<?> "Tried 12")
<|> (char '3' <?> "Tried 3")

5IFO SVOOJOH UIJT JO UIF 3&1-



1BSTFD ƌUSZ B ] Cƍ DPOTJEFSFE IBSNGVM &EXBSE ; :BOH
$)"15&3  1"34&3 $0.#*/"5034 

Prelude> trifP tryAnnot "13"


Failure (interactive):1:1: error: expected: Tried 12,
Tried 3
13<EOF>
^

/PX UIF FSSPS XJMM MJTU UIF QBSTFT JU BUUFNQUFE CFGPSF JU GBJMFE
:PVƊMM XBOU UP NBLF UIF BOOPUBUJPOT NPSF JOGPSNBUJWF UIBO
XIBU XF EFNPOTUSBUFE JO ZPVS PXO QBSTFST

 .BSTIBMMJOH GSPN BO "45 UP B


EBUBUZQF
'BJS XBSOJOH 5IJT TFDUJPO SFMJFT PO B MJUUMF NPSF CBDLHSPVOE
LOPXMFEHF GSPN ZPV UIBO QSFWJPVT TFDUJPOT IBWF *G ZPV BSF
OPU B QFSTPO XIP BMSFBEZ IBT TPNF QSPHSBNNJOH FYQFSJFODF
UIF GPMMPXJOH NBZ OPU TFFN UFSSJCMZ VTFGVM UP ZPV BOE UIFSF
NBZ CF TPNF EJƸDVMU UP VOEFSTUBOE UFSNJOPMPHZ BOE DPO
DFQUT
5IF BDU PG QBSTJOH JO B TFOTF JT B NFBOT PG ƌOFDLJOH EPXOƍ
UIF DBSEJOBMJUZ PG PVS JOQVUT UP UIF TFU PG UIJOHT PVS QSPHSBNT
IBWF B TFOTJCMF BOTXFS GPS *UƊT FYUSFNFMZ VOMJLFMZ ZPV DBO EP
TPNFUIJOH NFBOJOHGVM BOE EPNBJOTQFDJƶD XIFO ZPVS JOQVU
UZQF JT String Text PS ByteString )PXFWFS JG ZPV DBO QBSTF POF
PG UIPTF UZQFT JOUP TPNFUIJOH TUSVDUVSFE SFKFDUJOH CBE JOQVUT
UIFO ZPV NJHIU CF BCMF UP XSJUF B QSPQFS QSPHSBN 0OF PG UIF
$)"15&3  1"34&3 $0.#*/"5034 

NJTUBLFT QSPHSBNNFST NBLF JO XSJUJOH QSPHSBNT IBOEMJOH


UFYU JT JO BMMPXJOH UIFJS EBUB UP TUBZ JO UIF UFYUVBM GPSNBU EPJOH
NJOECFOEJOH CBDLƷJQT UP DPQF XJUI UIF VOTUSVDUVSFE OBUVSF
PG UFYUVBM JOQVUT
*O TPNF DBTFT UIF BDU PG QBSTJOH JTOƊU FOPVHI :PV NJHIU
IBWF B TPSU PG "45 PS TUSVDUVSFE SFQSFTFOUBUJPO PG XIBU XBT
QBSTFE CVU GSPN UIFSF ZPV NJHIU FYQFDU UIBU "45 PS SFQ
SFTFOUBUJPO UP UBLF B QBSUJDVMBS GPSN 5IJT NFBOT XF XBOU UP
OBSSPX UIF DBSEJOBMJUZ BOE HFU FWFO NPSF TQFDJƶD BCPVU IPX
PVS EBUB MPPLT 0ǒFO UIJT TFDPOE TUFQ JT DBMMFE VONBSTIBMMJOH
PVS EBUB 4JNJMBSMZ NBSTIBMMJOH JT UIF BDU PG QSFQBSJOH EBUB
GPS TFSJBMJ[BUJPO XIFUIFS WJB NFNPSZ BMPOF GPSFJHO GVODUJPO
JOUFSGBDF CPVOEBSZ
PS PWFS B OFUXPSL JOUFSGBDF
5IF XIPMF JEFB IFSF JT UIBU ZPV IBWF UXP QJQFMJOFT GPS ZPVS
EBUB

Text -> Structure -> Meaning


-- parse -> unmarshall

Meaning -> Structure -> Text


-- marshall -> serialize

5IFSF JTOƊU POMZ POF XBZ UP BDDPNQMJTI UIJT CVU XFƊMM TIPX
ZPV B DPNNPOMZ VTFE MJCSBSZ BOE IPX JU IBT UIJT UXPTUBHF
QJQFMJOF JO UIF "1*
$)"15&3  1"34&3 $0.#*/"5034 

.BSTIBMMJOH BOE VONBSTIBMMJOH +40/ EBUB


aeson JT QSFTFOUMZ UIF NPTU QPQVMBS +40/ MJCSBSZ JO )BTLFMM
0OF PG UIF UIJOHT UIBUƊMM DPOGVTF QSPHSBNNFST DPNJOH UP
)BTLFMM GSPN 1ZUIPO 3VCZ $MPKVSF +BWB4DSJQU PS TJNJMBS
MBOHVBHFT JT UIBU UIFSFƊT VTVBMMZ OP VONBSTIBMMNBSTIBMM TUFQ
*OTUFBE UIF SBX +40/ "45 XJMM CF SFQSFTFOUFE EJSFDUMZ BT BO
VOUZQFE CMPC PG EBUB 6TFST PG UZQFE MBOHVBHFT BSF NPSF MJLFMZ
UP IBWF FODPVOUFSFE TPNFUIJOH MJLF UIJT 8FƊMM CF VTJOH aeson
 GPS UIF GPMMPXJOH FYBNQMFT

{-# LANGUAGE OverloadedStrings #-}


{-# LANGUAGE QuasiQuotes #-}

module Marshalling where

import Data.Aeson
import Data.ByteString.Lazy (ByteString)
import Text.RawString.QQ

https://en.wikipedia.org/wiki/JSON
$)"15&3  1"34&3 $0.#*/"5034 

sectionJson :: ByteString
sectionJson = [r|
{ "section": {"host": "wikipedia.org"},
"whatisit": {"red": "intoothandclaw"}
}
|]

/PUF UIBU XFƊSF TBZJOH UIF UZQF PG sectionJson JT B MB[Z ByteString


*G ZPV HFU TUSJDU BOE MB[Z #ZUF4USJOH UZQFT NJYFE VQ ZPVƊMM HFU
FSSPST MJLF UIF GPMMPXJOH

1SPWJEFE B TUSJDU #ZUF4USJOH XIFO B MB[Z POF XBT FYQFDUFE

<interactive>:10:8:
Couldn't match expected type
Data.ByteString.Lazy.Internal.ByteString
with actual type ByteString

NB:
Data.ByteString.Lazy.Internal.ByteString
is defined in
Data.ByteString.Lazy.Internal

ByteString
is defined in
Data.ByteString.Internal
$)"15&3  1"34&3 $0.#*/"5034 

5IF ƌBDUVBM UZQFƍ JT XIBU XF QSPWJEFE UIF ƌFYQFDUFE UZQFƍ


JT XIBU UIF UZQFT XBOUFE 5IF NB: JO UIF UZQF FSSPS TUBOET
GPS ƌOPUB CFOFƍ &JUIFS XF VTFE UIF XSPOH DPEF TP FYQFDUFE
UZQF OFFET UP DIBOHF
PS XF QSPWJEFE UIF XSPOH WBMVFT BDUVBM
UZQF PVS UZQFTWBMVFT OFFE UP DIBOHF
 :PV DBO SFQSPEVDF
UIJT FSSPS CZ NBLJOH UIF GPMMPXJOH NJTUBLF JO UIF NBSTIBMMJOH
NPEVMF

-- Change the import of the ByteString type constructor from:


import Data.ByteString.Lazy (ByteString)

-- Into:
import Data.ByteString (ByteString)
$)"15&3  1"34&3 $0.#*/"5034 

1SPWJEFE B MB[Z #ZUF4USJOH XIFO B TUSJDU POF XBT FYQFDUFE

{-# LANGUAGE OverloadedStrings #-}


{-# LANGUAGE QuasiQuotes #-}

module WantedStrict where

import Data.Aeson
import Data.ByteString.Lazy (ByteString)
import Text.RawString.QQ

sectionJson :: ByteString
sectionJson = [r|
{ "section": {"host": "wikipedia.org"},
"whatisit": {"red": "intoothandclaw"}
}
|]

main = do
let blah :: Maybe Value
blah = decodeStrict sectionJson
print blah

:PVƊMM HFU UIF GPMMPXJOH UZQF FSSPS JG ZPV MPBE UIBU VQ

code/wantedStrictGotLazy.hs:19:27:
$)"15&3  1"34&3 $0.#*/"5034 

Couldn't match expected type


‘Data.ByteString.Internal.ByteString’
with actual type ‘ByteString’
NB:
‘Data.ByteString.Internal.ByteString’
is defined in ‘Data.ByteString.Internal’
‘ByteString’ is defined in ‘Data.ByteString.Lazy.Internal’

In the first argument of ‘decodeStrict’,


namely ‘sectionJson’
In the expression: decodeStrict sectionJson

5IF NPSF VTFGVM JOGPSNBUJPO JT JO UIF NB: PS OPUB CFOF XIFSF


UIF JOUFSOBM NPEVMFT BSF NFOUJPOFE 5IF LFZ JT UP SFNFNCFS
ƉBDUVBM UZQFƊ NFBOT ƌZPVS DPEFƍ ƉFYQFDUFE UZQFƊ NFBOT ƌXIBU
UIFZ FYQFDUFE ƍ BOE UIBU UIF #ZUF4USJOH NPEVMF UIBU EPFTOƊU
IBWF -B[Z JO UIF OBNF JT UIF TUSJDU WFSTJPO 8F DBO NPEJGZ
PVS DPEF B CJU UP HFU OJDFS UZQF FSSPST

-- replace the (ByteString) import with these


import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS

-- edit the type sig for this one


sectionJson :: LBS.ByteString

5IFO XFƊMM HFU UIF GPMMPXJOH UZQF FSSPS JOTUFBE


$)"15&3  1"34&3 $0.#*/"5034 

Couldn't match expected type ‘BS.ByteString’


with actual type ‘LBS.ByteString’

NB: ‘BS.ByteString’ is defined in


‘Data.ByteString.Internal’

‘LBS.ByteString’ is defined in
‘Data.ByteString.Lazy.Internal’
In the first argument of ‘decodeStrict’,
namely ‘sectionJson’
In the expression: decodeStrict sectionJson

5IJT JT IFMQGVM CFDBVTF XF IBWF CPUI WFSTJPOT BWBJMBCMF BT


RVBMJƶFE NPEVMFT :PV NBZ OPU BMXBZT CF TP GPSUVOBUF BOE
XJMM OFFE UP SFNFNCFS XIJDI JT XIJDI

#BDL UP UIFƒ+40/

-FUƊT HFU CBDL UP IBOEMJOH +40/ 5IF NPTU DPNNPO GVODUJPOT


GPS VTJOH aeson BSF UIF GPMMPXJOH

Prelude> import Data.Aeson


Prelude> :t encode
encode :: ToJSON a => a -> LBS.ByteString
Prelude> :t decode
decode :: FromJSON a => LBS.ByteString -> Maybe a
$)"15&3  1"34&3 $0.#*/"5034 

5IFTF GVODUJPOT BSF TPSU PG FMJEJOH UIF JOUFSNFEJBUF TUFQ


UIBU QBTTFT UISPVHI UIF 7BMVF UZQF JO aeson XIJDI JT B EBUBUZQF
+40/ "45 ƈ ƌTPSU PG ƍ CFDBVTF ZPV DBO EFDPEF UIF SBX +40/
EBUB JOUP B 7BMVF BOZXBZ

Prelude> decode sectionJson :: Maybe Value


Just (Object (fromList [
("whatisit",
Object (fromList [("red",
String "intoothandclaw")])),
("section",
Object (fromList [("host",
String "wikipedia.org")]))]))

/PU VI TVQFS QSFUUZ 8FƊMM ƶHVSF PVU TPNFUIJOH OJDFS JO


B NPNFOU "MTP EP OPU GPSHFU UP BTTFSU B UZQF PS UIF UZQF
EFGBVMUJOH JO ()$J XJMM EP TJMMZ UIJOHT

Prelude> decode sectionJson


Nothing

/PX XIBU JG XF EP XBOU B OJDFS SFQSFTFOUBUJPO GPS UIJT +40/


OPJTF 8FMM MFUƊT EFƶOF PVS EBUBUZQFT BOE TFF JG XF DBO EFDPEF
UIF +40/ JOUP PVS UZQF
$)"15&3  1"34&3 $0.#*/"5034 

{-# LANGUAGE OverloadedStrings #-}


{-# LANGUAGE QuasiQuotes #-}

module Marshalling where

import Control.Applicative
import Data.Aeson
import Data.ByteString.Lazy (ByteString)
import qualified Data.Text as T
import Data.Text (Text)
import Text.RawString.QQ

sectionJson :: ByteString
sectionJson = [r|
{ "section": {"host": "wikipedia.org"},
"whatisit": {"red": "intoothandclaw"}
}
|]

data TestData =
TestData {
section :: Host
, what :: Color
} deriving (Eq, Show)

newtype Host =
Host String
$)"15&3  1"34&3 $0.#*/"5034 

5IJT XJMM JO GBDU OFU ZPV B UZQF FSSPS DPNQMBJOJOH BCPVU


UIFSF OPU CFJOH BO JOTUBODF PG 'SPN+40/ GPS 5FTU%BUB 8IJDI
JT USVF ()$ IBT OP JEFB IPX UP VONBSTIBMM +40/ EBUB JO UIF
GPSN PG B 7BMVF
JOUP B 5FTU%BUB WBMVF -FUƊT BEE BO JOTUBODF
TP JU LOPXT IPX

instance FromJSON TestData where


parseJSON (Object v) =
TestData <$> v .: "section"
<*> v .: "whatisit"
parseJSON _ =
fail "Expected an object for TestData"

instance FromJSON Host where


parseJSON (Object v) =
Host <$> v .: "host"
parseJSON _ =
fail "Expected an object for Host"

instance FromJSON Color where


parseJSON (Object v) =
(Red <$> v .: "red")
<|> (Blue <$> v .: "blue")
<|> (Yellow <$> v .: "yellow")
parseJSON _ = fail "Expected an object for Color"
$)"15&3  1"34&3 $0.#*/"5034 

"MTP OPUF UIBU ZPV DBO VTF RVBTJRVPUFT UP BWPJE IBWJOH UP


FTDBQF RVPUBUJPO NBSLT JO UIF 3&1- BT XFMM

Prelude> :set -XOverloadedStrings


Prelude> decode "{\"blue\": \"123\"}" :: Maybe Color
Just (Blue "123")
Prelude> :set -XQuasiQuotes
Prelude> decode [r|{"red": "123"}|] :: Maybe Color
Just (Red "123")

5P SFMBUF XIBU XF KVTU EJE CBDL UP UIF SFMBUJPOTIJQ CFUXFFO


QBSTJOH BOE NBSTIBMMJOH UIF JEFB JT UIBU PVS 'SPN+40/ JO
TUBODF JT BDDFQUJOH UIF 7BMVF UZQF BOE 5P+40/ JOTUBODFT HFO
FSBUF UIF 7BMVF UZQF DMPTJOH UIF GPMMPXJOH MPPQ

-- FromJSON
ByteString -> Value -> yourType
-- parse -> unmarshall

-- ToJSON
yourType -> Value -> ByteString
-- marshall -> serialize

5IF EFƶOJUJPO PG 7BMVF BU UJNF PG XSJUJOH JT UIF GPMMPXJOH


$)"15&3  1"34&3 $0.#*/"5034 

-- | A JSON value represented as a Haskell value.


data Value = Object !Object
| Array !Array
| String !Text
| Number !Scientific
| Bool !Bool
| Null
deriving (Eq, Read, Show, Typeable, Data)

8IBU JG XF XBOU UP VONBSTIBMM TPNFUIJOH UIBU DPVME CF B


/VNCFS PS B 4USJOH

data NumberOrString =
Numba Integer
| Stringy Text
deriving (Eq, Show)

instance FromJSON NumberOrString where


parseJSON (Number i) = return $ Numba i
parseJSON (String s) = return $ Stringy s
parseJSON _ =
fail "NumberOrString must be number or string"

5IJT XPOƊU RVJUF XPSL BU ƶSTU 5IF USPVCMF JT UIBU +40/ BOE
+BWB4DSJQU BT JU IBQQFOT
POMZ IBT POF OVNFSJD UZQF BOE UIBU
$)"15&3  1"34&3 $0.#*/"5034 

UZQF JT B *&&& ƷPBU +40/ BOE +BWB4DSJQU UFSSJGZJOHMZ

IBWF OP JOUFHSBM UZQFT PS JOUFHFST TP aeson IBT UP QJDL POF


SFQSFTFOUBUJPO UIBU XPSLT GPS BMM QPTTJCMF +40/ OVNCFST 5IF
NPTU QSFDJTF XBZ UP EP UIBU JT UIF 4DJFOUJƶD UZQF XIJDI JT BO
BSCJUSBSJMZ QSFDJTF OVNFSJDBM UZQF ZPV NBZ SFNFNCFS UIJT
GSPN XBZ CBDL JO $IBQUFS #BTJD %BUBUZQFT
 4P XF OFFE UP
DPOWFSU GSPN B 4DJFOUJƶD UP BO *OUFHFS

import Control.Applicative
import Data.Aeson
import Data.ByteString.Lazy (ByteString)
import qualified Data.Text as T
import Data.Text (Text)
import Text.RawString.QQ
import Data.Scientific (floatingOrInteger)

data NumberOrString =
Numba Integer
| Stringy Text
deriving (Eq, Show)

https://en.wikipedia.org/wiki/IEEE_floating_point
$)"15&3  1"34&3 $0.#*/"5034 

instance FromJSON NumberOrString where


parseJSON (Number i) =
case floatingOrInteger i of
(Left _) -> fail "Must be integral number"
(Right integer) -> return $ Numba integer
parseJSON (String s) = return $ Stringy s
parseJSON _ =
fail "NumberOrString must be number or string"

-- so it knows what we want to parse


dec :: ByteString
-> Maybe NumberOrString
dec = decode

eitherDec :: ByteString
-> Either String NumberOrString
eitherDec = eitherDecode

main = do
print $ dec "blah"

/PX MFUƊT HJWF JU B XIJSM

Prelude> main
Nothing
$)"15&3  1"34&3 $0.#*/"5034 

#VU XIBU IBQQFOFE 8F DBO SFXSJUF UIF DPEF UP VTF eitherDec


UP HFU B TMJHIUMZ NPSF IFMQGVM UZQF FSSPS

main = do
print $ dec "blah"
print $ eitherDec "blah"

5IFO SFMPBEJOH UIF DPEF BOE USZJOH BHBJO JO UIF 3&1-

Prelude> main
Nothing
Left "Error in $: Failed reading:
not a valid json value"

#Z UIBU NFBOT XF BSF BCMF UP HFU NPSF JOGPSNBUJWF FSSPST


GSPN "FTPO *G XF XBOUFE TPNF FYBNQMFT UIBU XPSLFE XF
DPVME USZ UIJOHT MJLF UIF GPMMPXJOH

Prelude> dec "123"


Just (Numba 123)
Prelude> dec "\"blah\""
Just (Stringy "blah")

*UƊT XPSUI HFUUJOH DPNGPSUBCMF XJUI "FTPO FWFO JG ZPV EPOƊU


QMBO UP XPSL XJUI NVDI +40/ CFDBVTF NBOZ TFSJBMJ[BUJPO
MJCSBSJFT JO )BTLFMM GPMMPX B TJNJMBS "1* QBUUFSO 1MBZ XJUI UIF
FYBNQMF BOE TFF IPX ZPV OFFE UP DIBOHF UIF UZQF PG dec UP
CF BCMF UP QBSTF B MJTU PG OVNCFST PS TUSJOHT
$)"15&3  1"34&3 $0.#*/"5034 

 $IBQUFS &YFSDJTFT


 8SJUF B QBSTFS GPS TFNBOUJD WFSTJPOT BT EFƶOFE CZ http://
semver.org/ "ǒFS NBLJOH B XPSLJOH QBSTFS XSJUF BO 0SE
JOTUBODF GPS UIF SemVer UZQF UIBU PCFZT UIF TQFDJƶDBUJPO
PVUMJOFE PO UIF 4FN7FS XFCTJUF

-- Relevant to precedence/ordering,
-- cannot sort numbers like strings.
data NumberOrString =
NOSS String
| NOSI Integer

type Major = Integer


type Minor = Integer
type Patch = Integer
type Release = [NumberOrString]
type Metadata = [NumberOrString]

data SemVer =
SemVer Major Minor Patch Release Metadata

parseSemVer :: Parser SemVer


parseSemVer = undefined

&YQFDUFE SFTVMUT
$)"15&3  1"34&3 $0.#*/"5034 

Prelude> parseString parseSemVer mempty "2.1.1"


Success (SemVer 2 1 1 [] [])
Prelude> parseString parseSemVer mempty "1.0.0-x.7.z.92"
Success (SemVer 1 0 0 [NOSS "x", NOSI 7, NOSS "z", NOSI 92] []
Prelude> SemVer 2 1 1 [] [] > SemVer 2 1 0 [] []
True

 8SJUF B QBSTFS GPS QPTJUJWF JOUFHFS WBMVFT %POƊU SFVTF UIF


QSFFYJTUJOH digit PS integer GVODUJPOT CVU ZPV DBO VTF
UIF SFTU PG UIF MJCSBSJFT XFƊWF TIPXO ZPV TP GBS :PV BSF
OPU FYQFDUFE UP XSJUF B QBSTJOH MJCSBSZ GSPN TDSBUDI

parseDigit :: Parser Char


parseDigit = undefined

base10Integer :: Parser Integer


base10Integer = undefined

&YQFDUFE SFTVMUT

Prelude> parseString parseDigit mempty "123"


Success '1'
Prelude> parseString parseDigit mempty "abc"
Failure (interactive):1:1: error: expected: parseDigit
abc<EOF>
^
$)"15&3  1"34&3 $0.#*/"5034 

Prelude> parseString base10Integer mempty "123abc"


Success 123
Prelude> parseString base10Integer mempty "abc"
Failure (interactive):1:1: error: expected: integer
abc<EOF>
^

)JOU "TTVNF ZPVƊSF QBSTJOH CBTF OVNCFST 6TF BSJUI


NFUJD BT B DIFBQ ƌBDDVNVMBUPSƍ GPS ZPVS ƶOBM OVNCFS BT
ZPV QBSTF FBDI EJHJU MFǒUPSJHIU

 &YUFOE UIF QBSTFS ZPV XSPUF UP IBOEMF OFHBUJWF BOE QPT


JUJWF JOUFHFST 5SZ XSJUJOH B OFX QBSTFS JO UFSNT PG UIF
POF ZPV BMSFBEZ IBWF UP EP UIJT

Prelude> parseString base10Integer' mempty "-123abc"


Success (-123)

 8SJUF B QBSTFS GPS 64$BOBEB QIPOF OVNCFST XJUI WBSZ


JOH GPSNBUT
$)"15&3  1"34&3 $0.#*/"5034 

type NumberingPlanArea = Int -- aka area code


type Exchange = Int
type LineNumber = Int

data PhoneNumber =
PhoneNumber NumberingPlanArea Exchange LineNumber
deriving (Eq, Show)

parsePhone :: Parser PhoneNumber


parsePhone = undefined

8JUI UIF GPMMPXJOH CFIBWJPS

Prelude> parseString parsePhone mempty "123-456-7890"


Success (PhoneNumber 123 456 7890)
Prelude> parseString parsePhone mempty "1234567890"
Success (PhoneNumber 123 456 7890)
Prelude> parseString parsePhone mempty "(123) 456-7890"
Success (PhoneNumber 123 456 7890)
Prelude> parseString parsePhone mempty "1-123-456-7890"
Success (PhoneNumber 123 456 7890)

$G 8JLJQFEJBƊT BSUJDMF PO ƌ/BUJPOBM DPOWFOUJPOT GPS XSJU


JOH UFMFQIPOF OVNCFSTƍ :PV BSF FODPVSBHFE UP BEBQU UIF
FYFSDJTF UP ZPVS MPDBMJUZƊT DPOWFOUJPOT JG UIFZ BSF OPU QBSU
PG UIF //"1 TDIFNF
$)"15&3  1"34&3 $0.#*/"5034 

 8SJUF B QBSTFS GPS B MPH ƶMF GPSNBU BOE TVN UIF UJNF
TQFOU JO FBDI BDUJWJUZ "EEJUJPOBMMZ QSPWJEF BO BMUFSOB
UJWF BHHSFHBUJPO PG UIF EBUB UIBU QSPWJEFT BWFSBHF UJNF
TQFOU QFS BDUJWJUZ QFS EBZ 5IF GPSNBU TVQQPSUT UIF VTF
PG DPNNFOUT XIJDI ZPVS QBSTFS XJMM IBWF UP JHOPSF 5IF
# DIBSBDUFST GPMMPXFE CZ B EBUF NBSL UIF CFHJOOJOH PG B
QBSUJDVMBS EBZ
-PH GPSNBU FYBNQMF

-- wheee a comment

# 2025-02-05
08:00 Breakfast
09:00 Sanitizing moisture collector
11:00 Exercising in high-grav gym
12:00 Lunch
13:00 Programming
17:00 Commuting home in rover
17:30 R&R
19:00 Dinner
21:00 Shower
21:15 Read
22:00 Sleep

# 2025-02-07 -- dates not nececessarily sequential


08:00 Breakfast -- should I try skippin bfast?
$)"15&3  1"34&3 $0.#*/"5034 

09:00 Bumped head, passed out


13:36 Wake up, headache
13:37 Go to medbay
13:40 Patch self up
13:45 Commute home for rest
14:15 Read
21:00 Dinner
21:15 Read
22:00 Sleep

:PV BSF UP EFSJWF B SFBTPOBCMF EBUBUZQF GPS SFQSFTFOU


JOH UIJT EBUB ZPVSTFMG 'PS CPOVT QPJOUT NBLF UIJT CJ
EJSFDUJPOBM CZ NBLJOH B 4IPX SFQSFTFOUBUJPO GPS UIF EBUBUZQF
XIJDI NBUDIFT UIF GPSNBU ZPV BSF QBSTJOH 5IFO XSJUF B
HFOFSBUPS GPS UIJT EBUB VTJOH 2VJDL$IFDLƊT (FO BOE TFF JG
ZPV DBO CSFBL ZPVS QBSTFS XJUI 2VJDL$IFDL

 8SJUF B QBSTFS GPS *1W BEESFTTFT

import Data.Word

data IPAddress =
IPAddress Word32
deriving (Eq, Ord, Show)

" CJU XPSE JT B CJU VOTJHOFE JOU -PXFTU WBMVF JT 


SBUIFS UIBO CFJOH DBQBCMF PG SFQSFTFOUJOH OFHBUJWF OVN
$)"15&3  1"34&3 $0.#*/"5034 

CFST CVU UIF IJHIFTU QPTTJCMF WBMVF JO UIF TBNF OVNCFS


PG CJUT JT UXJDF BT IJHI /PUF

Prelude> import Data.Int


Prelude> import Data.Word
Prelude> maxBound :: Int32
2147483647
Prelude> maxBound :: Word32
4294967295
Prelude> div 4294967295 2147483647
2

8PSE JT BO BQQSPQSJBUF BOE DPNQBDU XBZ UP SFQSFTFOU


*1W BEESFTTFT :PV BSF FYQFDUFE UP ƶHVSF PVU OPU POMZ
IPX UP QBSTF UIF UZQJDBM *1 BEESFTT GPSNBU CVU IPX *1
BEESFTTFT XPSL OVNFSJDBMMZ JOTPGBS BT JT SFRVJSFE UP XSJUF
B XPSLJOH QBSTFS 5IJT XJMM SFRVJSF VTJOH B TFBSDI FOHJOF
VOMFTT ZPV IBWF BO BQQSPQSJBUF CPPL PO JOUFSOFU OFUXPSL
JOH IBOEZ
&YBNQMF *1W BEESFTTFT BOE UIFJS EFDJNBM SFQSFTFOUB
UJPOT

172.16.254.1 -> 2886794753


204.120.0.15 -> 3430416399

 4BNF BT CFGPSF CVU *1W


$)"15&3  1"34&3 $0.#*/"5034 

import Data.Word

data IPAddress6 =
IPAddress6 Word64 Word64
deriving (Eq, Ord, Show)

&YBNQMF *1W BEESFTTFT BOE UIFJS EFDJNBM SFQSFTFOUB


UJPOT

0:0:0:0:0:ffff:ac10:fe01 -> 281473568538113


0:0:0:0:0:ffff:cc78:f -> 281474112159759

FE80:0000:0000:0000:0202:B3FF:FE1E:8329 ->
338288524927261089654163772891438416681

2001:DB8::8:800:200C:417A ->
42540766411282592856906245548098208122

0OF PG UIF USJDLJFS QBSUT BCPVU *1W XJMM CF GVMM WT DPM
MBQTFE BEESFTTFT BOE UIF BCCSFWBUJPOT 4FF UIJT 2"
UISFBE BCPVU *1W BCCSFWJBUJPOT GPS NPSF
&OTVSF ZPV DBO QBSTF BCCSFWJBUFE WBSJBUJPOT PG UIF FBSMJFS
FYBNQMFT MJLF

FE80::0202:B3FF:FE1E:8329

http://answers.google.com/answers/threadview/id/770645.html
$)"15&3  1"34&3 $0.#*/"5034 

2001:DB8::8:800:200C:417A

 3FNPWF UIF EFSJWFE 4IPX JOTUBODFT GSPN UIF *1"EESFTT*1"E


ESFTT UZQFT XSJUF ZPVS PXO 4IPX JOTUBODF GPS FBDI UZQF
UIBU SFOEFST JO UIF UZQJDBM UFYUVBM GPSNBU BQQSPQSJBUF UP
FBDI

 8SJUF B GVODUJPO UIBU DPOWFSUT CFUXFFO *1"EESFTT BOE


*1"EESFTT

 8SJUF B QBSTFS GPS UIF %05 MBOHVBHF UIBU (SBQIWJ[ VTFT
UP FYQSFTT HSBQIT JO QMBJOUFYU
8F TVHHFTU ZPV MPPL BU UIF "45 EBUBUZQF JO )BQIWJ[ GPS
JEFBT PO IPX UP SFQSFTFOU UIF HSBQI JO B )BTLFMM EBUBUZQF
*G ZPVƊSF GFFMJOH FTQFDJBMMZ SPCVTU ZPV DBO USZ VTJOH GHM 

 %FƶOJUJPOT
 " QBSTFS QBSTFT
:PV SFBE UIF DIBQUFS SJHIU

 " QBSTFS DPNCJOBUPS DPNCJOFT UXP PS NPSF QBSTFST UP QSP


EVDF B OFX QBSTFS (PPE FYBNQMFT PG UIJT BSF UIJOHT MJLF
VTJOH <|> GSPN "MUFSOBUJWF UP QSPEVDF B OFX QBSTFS GSPN

http://www.graphviz.org/doc/info/lang.html

http://hackage.haskell.org/package/haphviz

http://hackage.haskell.org/package/fgl
$)"15&3  1"34&3 $0.#*/"5034 

UIF EJTKVODUJPO PG UXP QBSTFS BSHVNFOUT UP <|> 0S some


0S many 0S mappend 0S (>>)

 .BSTIBMMJOH JT USBOTGPSNJOH B QPUFOUJBMMZ OPOMJOFBS SFQ


SFTFOUBUJPO PG EBUB JO NFNPSZ JOUP B GPSNBU UIBU DBO CF
TUPSFE PO EJTL PS USBOTNJUUFE PWFS B OFUXPSL TPDLFU (P
JOH JO UIF PQQPTJUF EJSFDUJPO JT DBMMFE VONBSTIBMMJOH $G
TFSJBMJ[BUJPO BOE EFTFSJBMJ[BUJPO

 " UPLFO J[FS


DPOWFSUT UFYU VTVBMMZ B TUSFBN PG DIBSBDUFST
JOUP NPSF NFBOJOHGVM PS ƌDIVOLJFSƍ TUSVDUVSFT TVDI BT
XPSET TFOUFODFT PS TZNCPMT 5IF lines BOE words GVOD
UJPOT ZPVƊWF VTFE FBSMJFS JO UIJT CPPL BSF MJLF WFSZ VOTP
QIJTUJDBUFE UPLFOJ[FST

 -FYFS ƈ TFF UPLFOJ[FS

 'PMMPXVQ SFTPVSDFT


 1BSTFD USZ BPSC DPOTJEFSFE IBSNGVM &EXBSE ; :BOH

 $PEF DBTF TUVEZ QBSTJOH B CJOBSZ EBUB GPSNBU 3FBM 8PSME


)BTLFMM

 5IF 1BSTFD QBSTJOH MJCSBSZ 3FBM 8PSME )BTLFMM

 "O JOUSPEVDUJPO UP QBSTJOH UFYU JO )BTLFMM XJUI 1BSTFD


+BNFT 8JMTPO
http://unbui.lt/#!/post/haskell-parsec-basics
$)"15&3  1"34&3 $0.#*/"5034 

 1BSTJOH $44 XJUI 1BSTFD +BLVC "SOPME

 1BSTFD " QSBDUJDBM QBSTFS MJCSBSZ %BBO -FJKFO &SJL .FJ


KFS
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.
5200

 )PX UP 3FQMBDF 'BJMVSF CZ B -JTU PG 4VDDFTTFT 1IJMJQ


8BEMFS
http://dl.acm.org/citation.cfm?id=5288

 )PX UP 3FQMBDF 'BJMVSF CZ B )FBQ PG 4VDDFTTFT &EXBSE


,NFUU

 5XP LJOET PG CBDLUSBDLJOH 4BNVFM (©MJOFBV HFMJTBN



http://gelisam.blogspot.ca/2015/09/two-kinds-of-backtracking.
html

 -- BOE -3 JO $POUFYU 8IZ 1BSTJOH 5PPMT "SF )BSE +PTI


)BCFSNBO
http://blog.reverberate.org/2013/09/ll-and-lr-in-context-why-p
html

 1BSTJOH 5FDIOJRVFT B QSBDUJDBM HVJEF TFDPOE FEJUJPO


(SVOF  +BDPCT

 1BSTJOH +40/ XJUI "FTPO 4DIPPM PG )BTLFMM

 BFTPO  EBZT PG )BDLBHF 0MJWFS $IBSMFT


$IBQUFS 

$PNQPTJOH UZQFT

5IF MBTU UIJOH POF


EJTDPWFST JO DPNQPTJOH B
XPSL JT XIBU UP QVU ƶSTU

5 4 &MJPU


$)"15&3  & 1-63*#64 .0/"% 

 $PNQPTJOH UZQFT


5IJT DIBQUFS BOE UIF OFYU BSF BCPVU NPOBE USBOTGPSNFST CPUI
UIF QSJODJQMFT CFIJOE UIFN BOE UIF QSBDUJDBMJUJFT PG VTJOH UIFN
'PS NBOZ QSPHSBNNFST NPOBE USBOTGPSNFST BSF JOEJTUJO
HVJTIBCMF GSPN NBHJDL TP XF XBOU UP BQQSPBDI UIFN GSPN
CPUI BOHMFT BOE EFNPOTUSBUF UIBU UIFZ BSF CPUI DPNQSFIFOTJ
CMF WJB UIFJS UZQFT BOE RVJUF QSBDUJDBM JO OPSNBM QSPHSBNNJOH
'VODUPST BOE BQQMJDBUJWFT BSF CPUI DMPTFE VOEFS DPNQPTJ
UJPO UIJT NFBOT UIBU ZPV DBO DPNQPTF UXP GVODUPST PS UXP
BQQMJDBUJWFT
BOE SFUVSO BOPUIFS GVODUPS PS BQQMJDBUJWF BT
UIF DBTF NBZ CF
 5IJT JT OPU USVF PG NPOBET IPXFWFS XIFO
ZPV DPNQPTF UXP NPOBET UIF SFTVMU JT OPU OFDFTTBSJMZ BOPUIFS
.POBE 8F XJMM TFF UIJT TPPO
)PXFWFS UIFSF BSF NBOZ UJNFT JO ƌSFBM DPEFƍ XIFO DPN
QPTJOH NPOBET JT EFTJSBCMF %JƵFSFOU NPOBET BMMPX VT UP XPSL
XJUI EJƵFSFOU FƵFDUT $PNQPTJOH NPOBET BMMPXT ZPV UP CVJME
VQ DPNQVUBUJPOT XJUI NVMUJQMF FƵFDUT #Z TUBDLJOH GPS FY
BNQMF B .BZCF NPOBE XJUI BO *0 ZPV DBO CF QFSGPSNJOH
*0 BDUJPOT XIJMF BMTP CVJMEJOH VQ DPNQVUBUJPOT UIBU IBWF B
QPTTJCJMJUZ PG GBJMVSF IBOEMFE CZ UIF .BZCF NPOBE
" NPOBE USBOTGPSNFS JT B WBSJBOU PG BO PSEJOBSZ UZQF UIBU
UBLFT BO BEEJUJPOBM UZQF BSHVNFOU XIJDI JT BTTVNFE UP IBWF
B NPOBE JOTUBODF 'PS FYBNQMF .BZCF5 JT UIF USBOTGPSNFS
WBSJBOU PG UIF .BZCF UZQF 5IF USBOTGPSNFS WBSJBOU PG B UZQF
HJWFT VT B .POBE JOTUBODF UIBU CJOET PWFS CPUI CJUT PG TUSVDUVSF
$)"15&3  & 1-63*#64 .0/"% 

5IJT BMMPXT VT UP DPNQPTF NPOBET BOE DPNCJOF UIFJS FƵFDUT


(FUUJOH DPNGPSUBCMF XJUI NPOBE USBOTGPSNFST JT JNQPSUBOU UP
CFDPNJOH QSPƶDJFOU JO )BTLFMM TP XFƊSF HPJOH UP UBLF JU QSFUUZ
TMPXMZ BOE HP TUFQ CZ TUFQ :PV XPOƊU OFDFTTBSJMZ XBOU UP TUBSU
PVU FBSMZ PO EFƶOJOH B CVODI PG USBOTGPSNFS TUBDLT ZPVSTFMG
CVU GBNJMJBSJUZ XJUI UIFN XJMM IFMQ B HSFBU EFBM JO VTJOH PUIFS
QFPQMFƊT MJCSBSJFT
*O UIJT DIBQUFS XF XJMM

Ƒ EFNPOTUSBUF XIZ DPNQPTJOH UXP NPOBET EPFT OPU HJWF


ZPV BOPUIFS NPOBE

Ƒ FYBNJOF UIF *EFOUJUZ BOE $PNQPTF UZQFT

Ƒ NBOJQVMBUF UZQFT VOUJM XF DBO NBLF NPOBET DPNQPTF

Ƒ NFFU TPNF DPNNPO NPOBE USBOTGPSNFST

Ƒ XPSL UISPVHI BO *EFOUJUZ DSJTJT

 $PNNPO GVODUJPOT BT UZQFT


8FƊMM TUBSU JO B QMBDF UIBU NBZ TFFN B MJUUMF TUSBOHF BOE QPJOU
MFTT BU ƶSTU XJUI OFXUZQFT UIBU DPSSFTQPOE UP TPNF WFSZ CBTJD
GVODUJPOT 8F DBO DPOTUSVDU UZQFT UIBU BSF MJLF UIPTF GVOD
UJPOT CFDBVTF XF IBWF UZQFT UIBU DBO UBLF BSHVNFOUT ƈ UIBU
JT UZQF DPOTUSVDUPST *O QBSUJDVMBS XFƊMM CF VTJOH UZQFT UIBU
DPSSFTQPOE UP id BOE (.)
$)"15&3  & 1-63*#64 .0/"% 

:PVƊWF TFFO TPNF PG UIF UZQFT XFƊSF HPJOH UP VTF JO UIF


GPMMPXJOH TFDUJPOT CFGPSF CVU XFƊMM CF QVUUJOH UIFN UP TPNF
OPWFM VTFT 5IF JEFB IFSF JT UP VTF UIFTF EBUBUZQFT BT IFMQFST JO
PSEFS UP EFNPOTUSBUF UIF QSPCMFNT XJUI DPNQPTJOH NPOBET
BOE XFƊMM TFF IPX UIFTF UZQF DPOTUSVDUPST DBO BMTP TFSWF BT
NPOBE USBOTGPSNFST CFDBVTF B NPOBE USBOTGPSNFS JT B UZQF
DPOTUSVDUPS UIBU UBLFT B NPOBE BT BO BSHVNFOU

*EFOUJUZ JT CPSJOH
:PVƊWF TFFO UIJT UZQF JO QSFWJPVT DIBQUFST TPNFUJNFT BT B
EBUBUZQF BOE TPNFUJNFT BT B OFXUZQF 8FƊMM DPOTUSVDU UIF
UZQF EJƵFSFOUMZ UIJT UJNF BT B OFXUZQF XJUI B IFMQFS GVODUJPO
PG UIF TPSU XF TBX JO 3FBEFS BOE 4UBUF

newtype Identity a =
Identity { runIdentity :: a }

8FƊMM CF VTJOH UIF OFXUZQF JO UIJT DIBQUFS CFDBVTF UIF


NPOBE USBOTGPSNFS WFSTJPO *EFOUJUZ5 JT VTVBMMZ XSJUUFO BT
B OFXUZQF 5IF VTF PG UIF QSFƶYFT ƌSVOƍ PS ƌHFUƍ JOEJDBUFT
UIBU UIFTF BDDFTTPS GVODUJPOT BSF NFBOT PG FYUSBDUJOH UIF VO
EFSMZJOH WBMVF GSPN UIF UZQF 5IFSF JT OP SFBM EJƵFSFODF JO
NFBOJOH CFUXFFO ƌSVOƍ BOE ƌHFUƍ :PVƊMM TFF UIFTF BDDFTTPS
GVODUJPOT PǒFO QBSUJDVMBSMZ XJUI VUJMJUZ UZQFT MJLF *EFOUJUZ PS
USBOTGPSNFS WBSJBOUT SFVTJOH BO PSJHJOBM UZQF
$)"15&3  & 1-63*#64 .0/"% 

" OPUF BCPVU OFXUZQFT 8IJMF NPOBE USBOTGPSNFS UZQFT DPVME


CF XSJUUFO VTJOH UIF data LFZXPSE UIFZ BSF NPTU DPNNPOMZ
XSJUUFO BT OFXUZQFT BOE XFƊMM CF TUJDLJOH XJUI UIBU QBUUFSO
IFSF 5IFZ BSF POMZ OFXUZQFE UP BWPJE VOOFDFTTBSZ PWFSIFBE
BT OFXUZQFT BT XF SFDBMM IBWF BO VOEFSMZJOH SFQSFTFOUBUJPO
JEFOUJDBM UP UIF UZQF UIFZ DPOUBJO 5IF JNQPSUBOU UIJOH JT
UIBU NPOBE USBOTGPSNFST BSF OFWFS TVN PS QSPEVDU UZQFT
UIFZ BSF BMXBZT KVTU B NFBOT PG XSBQQJOH POF FYUSB MBZFS PG
NPOBEJD
TUSVDUVSF BSPVOE B UZQF TP UIFSF JT OFWFS B SFBTPO
UIFZ DPVMEOƊU CF OFXUZQFT )BTLFMMFST IBWF B HFOFSBM UFOEFODZ
UP BWPJE BEEJOH BEEJUJPOBM SVOUJNF PWFSIFBE JG UIFZ DBO TP JG
UIFZ DBO OFXUZQF JU UIFZ NPTU PǒFO XJMM
"OPUIFS UIJOH XF XBOU UP OPUJDF BCPVU *EFOUJUZ JT UIF TJN
JMBSJUZ PG UIF LJOE PG PVS *EFOUJUZ UZQF UP UIF UZQF PG UIF id
GVODUJPO BMUIPVHI UIF ƶEFMJUZ PG UIF DPNQBSJTPO JTOƊU QFSGFDU
HJWFO UIF MJNJUBUJPOT PG UZQFMFWFM DPNQVUBUJPO JO )BTLFMM

Prelude> :t id
id :: a -> a
Prelude> :k Identity
Identity :: * -> *

5IF LJOE TJHOBUVSF PG UIF UZQF SFTFNCMFT UIF UZQF TJHOBUVSF


PG UIF GVODUJPO XIJDI XF IPQF JTOƊU UPP NVDI PG B TVSQSJTF
'JOF TP GBS ƈ OPU NVDI OFX IFSF :FU
$)"15&3  & 1-63*#64 .0/"% 

$PNQPTF
8F NFOUJPOFE BCPWF UIBU XF DBO BMTP DPOTUSVDU B EBUBUZQF
UIBU DPSSFTQPOET UP GVODUJPO DPNQPTJUJPO
)FSF JT UIF $PNQPTF UZQF *U TIPVME MPPL UP ZPV NVDI MJLF
GVODUJPO DPNQPTJUJPO CVU JO UIJT DBTF UIF ԕ BOE Ԗ SFQSFTFOU
UZQF DPOTUSVDUPST OPU UFSNMFWFM GVODUJPOT

newtype Compose f g a =
Compose { getCompose :: f (g a) }
deriving (Eq, Show)

4P XF IBWF B UZQF DPOTUSVDUPS UIBU UBLFT UISFF UZQF BSHV


NFOUT ԕ BOE Ԗ NVTU CF UZQF DPOTUSVDUPST UIFNTFMWFT XIJMF
Ԑ XJMM CF B DPODSFUF UZQF DPOTJEFS UIF SFMBUJPOTIJQ CFUXFFO
UZQF DPOTUSVDUPST BOE UFSNMFWFM GVODUJPOT PO UIF POF IBOE
BOE WBMVFT BOE UZQF DPOTUBOUT PO UIF PUIFS
 "T XF EJE BCPWF
MFUƊT MPPL BU UIF LJOE PG $PNQPTF ƈ OPUF UIF LJOET PG UIF
BSHVNFOUT UP UIF UZQF DPOTUSVDUPS

Compose :: (* -> *) -> (* -> *) -> * -> *

%PFT UIBU SFNJOE ZPV PG BOZUIJOH

(.) :: (b -> c) -> (a -> b) -> a -> c

4P XIBU EPFT UIBU MPPL MJLF JO QSBDUJDF 4PNFUIJOH MJLF UIJT


$)"15&3  & 1-63*#64 .0/"% 

Prelude> Compose [Just 1, Nothing]


Compose {getCompose = [Just 1,Nothing]}

Prelude> :t Compose [Just (1 :: Int), Nothing]


Compose [Just (1 :: Int), Nothing] :: Compose [] Maybe Int

(JWFO UIF BCPWF WBMVF UIF UZQF WBSJBCMFT HFU CPVOE BDDPSE
JOHMZ

Compose [Just (1 :: Int), Nothing]

Compose { getCompose :: f (g a) }

Compose [] Maybe Int

f ~ []
g ~ Maybe
a ~ Int

8F IBWF POF CJU PG TUSVDUVSF XSBQQFE BSPVOE BOPUIFS UIFO


B WBMVF UZQF UIF Ԑ
CFDBVTF UIF XIPMF UIJOH TUJMM IBT UP CF LJOE
* JO UIF FOE 8FƊWF NBEF UIF QPJOU JO QSFWJPVT DIBQUFST UIBU
UZQF DPOTUSVDUPST BSF GVODUJPOT 5ZQF DPOTUSVDUPST DBO UBLF
PUIFS UZQF DPOTUSVDUPST BT BSHVNFOUT UPP KVTU BT GVODUJPOT
DBO UBLF PUIFS GVODUJPOT BT BSHVNFOUT 5IJT JT XIBU BMMPXT VT
UP DPNQPTF UZQFT
$)"15&3  & 1-63*#64 .0/"% 

 5XP MJUUMF GVODUPST TJUUJOƊ JO B USFF


-*'5*/(
-FUƊT TUBSU XJUI DPNQPTJOH GVODUPST VTJOH UIF UZQFT XFƊWF TFFO
KVTU BCPWF 8F LOPX XF DBO MJǒ PWFS *EFOUJUZ ZPVƊWF TFFO UIJT
'VODUPS CFGPSF

instance Functor Identity where


fmap f (Identity a) = Identity (f a)

*EFOUJUZ IFSF HJWFT VT B TPSU PG WBOJMMB 'VODUPS UIBU EPFTOƊU


SFBMMZ EP BOZUIJOH JOUFSFTUJOH CVU DBQUVSFT UIF FTTFODF PG XIBU
'VODUPST BSF BCPVU 5IF GVODUJPO HFUT MJǒFE JOUP UIF DPOUFYU
PG UIF *EFOUJUZ UZQF BOE UIFO NBQQFE PWFS UIF Ԑ WBMVF
*U UVSOT PVU XF DBO HFU B 'VODUPS JOTUBODF GPS $PNQPTF UPP
JG XF BTL UIBU UIF ԕ BOE Ԗ CPUI IBWF 'VODUPS JOTUBODFT

instance (Functor f, Functor g) =>


Functor (Compose f g) where
fmap f (Compose fga) =
Compose $ (fmap . fmap) f fga

/PX UIF ԕ BOE UIF Ԗ CPUI IBWF UP CF QBSU PG UIF TUSVDUVSF


UIBU XFƊSF MJǒJOH PWFS TP UIFZ CPUI IBWF UP CF 'VODUPST UIFN
TFMWFT 8F OFFE UP CF BCMF UP KVNQ PWFS CPUI UIPTF MBZFST JO
PSEFS UP BQQMZ UP UIF WBMVF UIBUƊT VMUJNBUFMZ JOTJEF 8F IBWF UP
$)"15&3  & 1-63*#64 .0/"% 

GNBQ UXJDF UP HFU UP UIBU WBMVF JOTJEF CFDBVTF PG UIF MBZFSFE


TUSVDUVSFT
5P SFUVSO UP UIF FYBNQMF XF VTFE BCPWF XF IBWF UIJT UZQF

newtype Compose f g a =
Compose { getCompose :: f (g a) }
deriving (Eq, Show)

Compose { getCompose :: f (g a) }

Compose [] Maybe Int

"OE JG XF VTF PVS 'VODUPS JOTUBODF XF DBO BQQMZ B GVODUJPO


UP UIF *OU WBMVF XSBQQFE VQ JO BMM UIBU TUSVDUVSF

Prelude> Compose [Just 1, Nothing]


Compose {getCompose = [Just 1,Nothing]}
Prelude> fmap (+1) (Compose [Just 1, Nothing])
Compose {getCompose = [Just 2,Nothing]}

8F DBO HFOFSBMJ[F UIJT UP EJƵFSFOU BNPVOUT PG TUSVDUVSF


TVDI BT XJUI POF MFTT CJU PG TUSVDUVSF :PV NBZ SFNFNCFS UIJT
GSPN B QSFWJPVT DIBQUFS
$)"15&3  & 1-63*#64 .0/"% 

newtype One f a =
One (f a)
deriving (Eq, Show)

instance Functor f =>


Functor (One f) where
fmap f (One fa) = One $ fmap f fa

0S POF NPSF MBZFS PG TUSVDUVSF UIBO $PNQPTF

newtype Three f g h a =
Three (f (g (h a)))
deriving (Eq, Show)

instance (Functor f, Functor g, Functor h) =>


Functor (Three f g h) where
fmap f (Three fgha) =
Three $ (fmap . fmap . fmap) f fgha

"T JU IBQQFOT KVTU BT XJUI UIF BOPOZNPVT QSPEVDU (,) BOE


UIF BOPOZNPVT TVN Either UIF $PNQPTF UZQF BMMPXT VT UP
FYQSFTT BSCJUSBSJMZ OFTUFE UZQFT

v :: Compose [] Maybe (Compose Maybe [] Integer)


v = Compose [Just (Compose $ Just [1])]
$)"15&3  & 1-63*#64 .0/"% 

5IF XBZ UP UIJOL BCPVU UIJT JT UIBU UIF DPNQPTJUJPO PG UXP


EBUBUZQFT UIBU IBWF B 'VODUPS JOTUBODF HJWFT SJTF UP B OFX 'VOD
UPS JOTUBODF :PVƊMM TPNFUJNFT TFF QFPQMF SFGFS UP UIJT BT 'VOD
UPST CFJOH ƌDMPTFE VOEFS DPNQPTJUJPOƍ XIJDI KVTU NFBOT UIBU
XIFO ZPV DPNQPTF UXP 'VODUPST ZPV HFU BOPUIFS 'VODUPS

 5XJOQMJDBUJWF
:PV QSPCBCMZ HVFTTFE UIJT XBT PVS OFYU TUFQ JO $PNQPTF
MBOEJB "QQMJDBUJWFT JU UVSOT PVU BSF BMTP DMPTFE VOEFS DPNQP
TJUJPO 8F DBO JOEFFE DPNQPTF UXP UZQFT UIBU IBWF "QQMJDBUJWF
JOTUBODFT BOE HFU B OFX "QQMJDBUJWF JOTUBODF #VU ZPVƊSF HPJOH
UP XSJUF JU
$)"15&3  & 1-63*#64 .0/"% 

(05$)" &YFSDJTF UJNF


-- instance types provided as they may help.

{-# LANGUAGE InstanceSigs #-}

instance (Applicative f, Applicative g) =>


Applicative (Compose f g) where
pure :: a -> Compose f g a
pure = undefined

(<*>) :: Compose f g (a -> b)


-> Compose f g a
-> Compose f g b
(Compose f) <*> (Compose a) = undefined

8F NFOUJPOFE JO BO FBSMJFS DIBQUFS UIBU "QQMJDBUJWF JT B


XFBLFS BMHFCSB UIBO .POBE BOE UIBU TPNFUJNFT UIFSF BSF
CFOFƶUT UP QSFGFSSJOH BO "QQMJDBUJWF XIFO ZPV EPOƊU OFFE UIF
GVMM QPXFS PG UIF .POBE 5IJT JT POF PG UIPTF CFOFƶUT 5P
DPNQPTF "QQMJDBUJWFT ZPV EPOƊU OFFE UP EP UIF MFHXPSL UIBU
NPOBET SFRVJSF JO PSEFS UP DPNQPTF BOE TUJMM IBWF B .POBE
0I ZFT SJHIU ƈ XF TUJMM IBWFOƊU RVJUF NBEF JU UP NPOBET
DPNQPTJOH CVU XFƊSF BCPVU UP
$)"15&3  & 1-63*#64 .0/"% 

 5XPOBE
8IBU BCPVU .POBE 5IFSFƊT OP QSPCMFN DPNQPTJOH UXP BSCJ
USBSZ EBUBUZQFT UIBU IBWF .POBE JOTUBODFT 8F TBX UIJT BMSFBEZ
XIFO XF VTFE $PNQPTF XJUI .BZCF BOE MJTU XIJDI CPUI IBWF
.POBE JOTUBODFT EFƶOFE )PXFWFS UIF SFTVMU PG IBWJOH EPOF
TP EPFT OPU HJWF ZPV B .POBE
5IF JTTVF DPNFT EPXO UP B MBDL PG JOGPSNBUJPO #PUI UZQFT
$PNQPTF JT XPSLJOH XJUI BSF QPMZNPSQIJD TP XIFO ZPV USZ
UP XSJUF CJOE GPS UIF .POBE ZPVƊSF USZJOH UP DPNCJOF UXP
QPMZNPSQIJD CJOET JOUP B TJOHMF DPNCJOFE CJOE 5IJT JU UVSOT
PVU JT OPU QPTTJCMF

{-# LANGUAGE InstanceSigs #-}

-- impossible.
instance (Monad f, Monad g) => Monad (Compose f g) where
return = pure

(>>=) :: Compose f g a
-> (a -> Compose f g b)
-> Compose f g b
(>>=) = ???

5IFTF BSF UIF UZQFT XFƊSF USZJOH UP DPNCJOF CFDBVTF ԕ BOE Ԗ


BSF OFDFTTBSJMZ CPUI NPOBET XJUI UIFJS PXO .POBE JOTUBODFT
$)"15&3  & 1-63*#64 .0/"% 

Monad f => f a -> (a -> f b) -> f b


Monad g => g a -> (a -> g b) -> g b

'SPN UIPTF XF BSF USZJOH UP XSJUF UIJT CJOE

(Monad f, Monad g) => f (g a) -> (a -> f (g b)) -> f (g b)

0S GPSNVMBUFE EJƵFSFOUMZ

(Monad f, Monad g) => f (g (f (g a))) -> f (g a)

"OE UIJT JT OPU QPTTJCMF 5IFSFƊT OPU B HPPE XBZ UP join UIBU
ƶOBM ԕ BOE Ԗ *UƊT B HSFBU FYFSDJTF UP USZ UP NBLF JU XPSL CFDBVTF
UIF CBSSJFST ZPVƊMM SVO JOUP BSF JOTUSVDUJWF JO UIFJS PXO SJHIU
:PV DBO BMTP SFBE $PNQPTJOH NPOBET CZ .BSL 1 +POFT BOE
-VD %VQPODIFFM UP TFF XIZ JUƊT OPU QPTTJCMF

/P GSFF CVSSJUP MVODIFT


4JODF HFUUJOH BOPUIFS .POBE HJWFO UIF DPNQPTJUJPO PG UXP
BSCJUSBSZ UZQFT UIBU IBWF B .POBE JOTUBODF JT JNQPTTJCMF XIBU
DBO XF EP UP HFU B .POBE JOTUBODF GPS DPNCJOBUJPOT PG UZQFT
5IF BOTXFS JT NPOBE USBOTGPSNFST 8FƊMM HFU UP UIBU BǒFS B MJUUMF
CSFBL GPS TPNF FYFSDJTFT

http://web.cecs.pdx.edu/~mpj/pubs/RR-1004.pdf
$)"15&3  & 1-63*#64 .0/"% 

 &YFSDJTFT $PNQPTF *OTUBODFT


$PNQPTF 'PMEBCMF
8SJUF UIF 'PMEBCMF JOTUBODF GPS $PNQPTF 5IF foldMap = undefined
CJU JT B IJOU UP NBLF JU FBTJFS BOE MPPL NPSF MJLF XIBU ZPVƊWF
TFFO BMSFBEZ

instance (Foldable f, Foldable g) =>


Foldable (Compose f g) where
foldMap = undefined

$PNQPTF 5SBWFSTBCMF
8SJUF UIF 5SBWFSTBCMF JOTUBODF GPS $PNQPTF

instance (Traversable f, Traversable g) =>


Traversable (Compose f g) where
traverse = undefined

"OE OPX GPS TPNFUIJOH DPNQMFUFMZ EJƵFSFOU


5IJT IBT OPUIJOH UP EP XJUI BOZUIJOH FMTF JO UIJT DIBQUFS
$)"15&3  & 1-63*#64 .0/"% 

class Bifunctor p where


{-# MINIMAL bimap | first, second #-}

bimap :: (a -> b) -> (c -> d) -> p a c -> p b d


bimap f g = first f . second g

first :: (a -> b) -> p a c -> p b c


first f = bimap f id

second :: (b -> c) -> p a b -> p a c


second = bimap id

*UƊT B GVODUPS UIBU DBO NBQ PWFS UXP UZQF BSHVNFOUT JOTUFBE
PG KVTU POF 8SJUF #JGVODUPS JOTUBODFT GPS UIF GPMMPXJOH UZQFT

 5IF MFTT ZPV UIJOL UIF FBTJFS JUƊMM CF

data Deux a b = Deux a b

 data Const a b = Const a

 data Drei a b c = Drei a b c

 data SuperDrei a b c = SuperDrei a b

 data SemiDrei a b c = SemiDrei a


$)"15&3  & 1-63*#64 .0/"% 

 data Quadriceps a b c d =
Quadzzz a b c d

 data Either a b =
Left a
| Right b

 .POBE USBOTGPSNFST


8FƊWF OPX TFFO XIBU UIF QSPCMFN XJUI .POBE JT ZPV DBO QVU
UXP UPHFUIFS CVU ZPV DBOƊU HFU B OFX .POBE JOTUBODF PVU PG JU
8IFO XF OFFE UP HFU B OFX .POBE JOTUBODF XF OFFE B NPOBE
USBOTGPSNFS *UƊT OPU NBHJD UIF BOTXFS JT JO UIF UZQFT
8F TBJE BCPWF UIBU B NPOBE USBOTGPSNFS JT B UZQF DPOTUSVD
UPS UIBU UBLFT B .POBE BT BO BSHVNFOU BOE SFUVSOT B .POBE
BT B SFTVMU 8F BMTP OPUFE UIBU UIF GVOEBNFOUBM QSPCMFN XJUI
DPNQPTJOH UXP .POBET MJFT JO UIF JNQPTTJCJMJUZ PG KPJOJOH UXP
VOLOPXO .POBET *O PSEFS UP NBLF UIBU KPJO IBQQFO XF OFFE
UP SFEVDF UIF QPMZNPSQIJTN BOE HFU DPODSFUF JOGPSNBUJPO
BCPVU POF PG UIF .POBET UIBU XFƊSF XPSLJOH XJUI 5IF PUIFS
.POBE SFNBJOT QPMZNPSQIJD BT B WBSJBCMF UZQF BSHVNFOU UP
PVS UZQF DPOTUSVDUPS 5SBOTGPSNFST IFMQ ZPV NBLF B NPOBE
PVU PG NVMUJQMF   
UZQFT UIBU FBDI IBWF B .POBE JO
TUBODF CZ XSBQQJOH BSPVOE FYJTUJOH NPOBET UIBU QSPWJEF FBDI
CJU PG XBOUFE GVODUJPOBMJUZ
$)"15&3  & 1-63*#64 .0/"% 

5IF UZQFT BSF USJDLZ IFSF TP XFƊSF HPJOH UP CF XBMLJOH


UISPVHI XSJUJOH NPOBE USBOTGPSNFST WFSZ TMPXMZ 1BSUT PG
XIBU GPMMPXT NBZ TFFN UFEJPVT TP XPSL UISPVHI JU BT TMPXMZ
PS RVJDLMZ BT ZPV OFFE UP

.POBEJD TUBDLJOH
"QQMJDBUJWF BMMPXT VT UP BQQMZ GVODUJPOT PG NPSF UIBO POF
BSHVNFOU JO UIF QSFTFODF PG GVODUPSJBM TUSVDUVSF FOBCMJOH VT
UP DPQF XJUI UIJT USBOTJUJPO

-- from this:
fmap (+1) (Just 1)

-- to this:
(,,) <$> Just 1 <*> Just "lol" <*> Just [1, 2]

4PNFUJNFT XF XBOU B (>>=) XIJDI DBO BEESFTT NPSF UIBO


POF .POBE BU PODF :PVƊMM PǒFO TFF UIJT JO BQQMJDBUJPOT UIBU
IBWF NVMUJQMF UIJOHT HPJOH PO TVDI BT B XFC BQQ XIFSF DPN
CJOJOH 3FBEFS BOE *0 JT DPNNPO :PV XBOU *0 TP ZPV DBO
QFSGPSN FƵFDUGVM BDUJPOT MJLF UBMLJOH UP B EBUBCBTF BOE BMTP
3FBEFS GPS UIF EBUBCBTF DPOOFDUJPO T
BOEPS )551 SFRVFTU
DPOUFYU 4PNFUJNFT ZPV NBZ FWFO XBOU NVMUJQMF 3FBEFST
BQQTQFDJƶD EBUB WT XIBU UIF GSBNFXPSL QSPWJEFT CZ EFGBVMU

BMUIPVHI VTVBMMZ UIFSFƊT B XBZ UP KVTU BEE UIF EBUB ZPV XBOU UP
B QSPEVDU UZQF PG B TJOHMF 3FBEFS
$)"15&3  & 1-63*#64 .0/"% 

4P UIF RVFTUJPO CFDPNFT IPX EP XF HFU POF CJH CJOE PWFS B


UZQF MJLF UIF GPMMPXJOH

IO (Reader String [a])

-- where the Monad instances involved


-- are that of IO, Reader, and []

%PJOH JU CBEMZ
8F DPVME NBLF POFPƵ UZQFT GPS FBDI DPNCJOBUJPO CVU UIJT
XJMM HFU UJSFTPNF RVJDLMZ 'PS FYBNQMF

newtype MaybeIO a =
MaybeIO { runMaybeIO :: IO (Maybe a) }

newtype MaybeList a =
MaybeList { runMaybeList :: [Maybe a] }

8F EPOƊU OFFE UP SFTPSU UP UIJT XF DBO HFU B .POBE GPS UXP


UZQFT BT MPOH BT XF LOPX XIBU POF PG UIF UZQFT JT 5SBOTGPSN
FST BSF B NFBOT PG BWPJEJOH NBLJOH B POFPƵ .POBE GPS FWFSZ
QPTTJCMF DPNCJOBUJPO PG UZQFT
$)"15&3  & 1-63*#64 .0/"% 

 *EFOUJUZ5
+VTU BT *EFOUJUZ IFMQT TIPX PƵ UIF NPTU CBTJD FTTFODF PG 'VOD
UPS "QQMJDBUJWF BOE .POBE IdentityT JT HPJOH UP IFMQ ZPV
CFHJO UP VOEFSTUBOE NPOBE USBOTGPSNFST 6TJOH UIJT UZQF UIBU
EPFTOƊU IBWF B MPU PG JOUFSFTUJOH TUVƵ HPJOH PO XJUI JU XJMM IFMQ
LFFQ VT GPDVTFE PO UIF UZQFT BOE UIF JNQPSUBOU GVOEBNFOUBMT
PG USBOTGPSNFST 8IBU XF TFF IFSF XJMM CF BQQMJDBCMF UP PUIFS
USBOTGPSNFST BT XFMM CVU UZQFT MJLF .BZCF BOE MJTU JOUSPEVDF
PUIFS QPTTJCJMJUJFT GBJMVSF DBTFT FNQUZ MJTUT
UIBU DPNQMJDBUF
UIJOHT B CJU
'JSTU MFUƊT DPNQBSF UIF *EFOUJUZ UZQF ZPVƊWF TFFO VQ UP UIJT
QPJOU BOE PVS OFX *EFOUJUZ5 EBUBUZQF

-- Plain old Identity. 'a' can be something with


-- more structure, but it's not required and
-- Identity won't know anything about it.
newtype Identity a =
Identity { runIdentity :: a }
deriving (Eq, Show)

-- The identity monad transformer, serving only to


-- to specify that additional structure should exist.
newtype IdentityT f a =
IdentityT { runIdentityT :: f a }
deriving (Eq, Show)
$)"15&3  & 1-63*#64 .0/"% 

8IBU DIBOHFE IFSF JT UIBU XF BEEFE BO FYUSB UZQF BSHVNFOU


5IFO XF XBOU 'VODUPS JOTUBODFT GPS CPUI *EFOUJUZ BOE *EFO
UJUZ5

instance Functor Identity where


fmap f (Identity a) = Identity (f a)

instance (Functor m) => Functor (IdentityT m) where


fmap f (IdentityT fa) = IdentityT (fmap f fa)

5IF *EFOUJUZ5 JOTUBODF IFSF TIPVME MPPL TJNJMBS UP UIF 'VOD


UPS JOTUBODF GPS UIF 0OF EBUBUZQF BCPWF ƈ UIF ԕԐ BSHVNFOU JT
UIF WBMVF JOTJEF UIF *EFOUJUZ5 XJUI UIF VOUPVDIBCMF
TUSVDUVSF
XSBQQFE BSPVOE JU "MM XF LOPX BCPVU UIBU BEEJUJPOBM MBZFS PG
TUSVDUVSF XSBQQFE BSPVOE UIF Ԑ WBMVF JT UIBU JU JT B 'VODUPS
8F BMTP XBOU "QQMJDBUJWF JOTUBODFT GPS FBDI
$)"15&3  & 1-63*#64 .0/"% 

instance Applicative Identity where


pure = Identity

(Identity f) <*> (Identity a) = Identity (f a)

instance (Applicative m) => Applicative (IdentityT m) where


pure x = IdentityT (pure x)

(IdentityT fab) <*> (IdentityT fa) =


IdentityT (fab <*> fa)

5IF *EFOUJUZ JOTUBODF TIPVME CF GBNJMJBS *O UIF *EFOUJUZ5


JOTUBODF UIF ԕԐԑ WBSJBCMF SFQSFTFOUT UIF f (a -> b) UIBU JT UIF
ƶSTU BSHVNFOU PG (<*>) 4JODF UIJT DBO SFMZ PO UIF "QQMJDBUJWF
JOTUBODF GPS Ԝ UP IBOEMF UIBU CJU UIJT JOTUBODF EFƶOFT IPX
UP BQQMJDBUJWFMZ BQQMZ JO UIF QSFTFODF PG UIBU PVUFS *EFOUJUZ5
MBZFS
'JOBMMZ XF XBOU TPNF .POBE JOTUBODFT
$)"15&3  & 1-63*#64 .0/"% 

instance Monad Identity where


return = pure

(Identity a) >>= f = f a

instance (Monad m) => Monad (IdentityT m) where


return = pure
(IdentityT ma) >>= f =
IdentityT $ ma >>= runIdentityT . f

5IF .POBE JOTUBODF JT USJDLZ TP XFƊSF HPJOH UP EP B GFX


UIJOHT UP CSFBL JU EPXO ,FFQ JO NJOE UIBU .POBE JT XIFSF XF
IBWF UP SFBMMZ VTF DPODSFUF UZQF JOGPSNBUJPO GSPN IdentityT
JO PSEFS UP NBLF UIF UZQFT ƶU

5IF CJOE CSFBLEPXO


8FƊMM TUBSU XJUI B DMPTFS MPPL BU UIF JOTUBODF BT XSJUUFO BCPWF

instance (Monad m) => Monad (IdentityT m) where


return = pure
(IdentityT ma) >>= f =
-- [ 1 ] [2] [3]
IdentityT $ ma >>= runIdentityT . f
-- [8] [4] [5] [7] [6]
$)"15&3  & 1-63*#64 .0/"% 

 'JSTU XF QBUUFSONBUDI PS VOQBDL UIF m a WBMVF PG IdentityT


m a WJB UIF EBUB DPOTUSVDUPS %PJOH UIJT IBT UIF UZQF
IdentityT m a -> m a BOE UIF UZQF PG ma JT m a 5IJT OPNFO
DMBUVSF EPFTOƊU NFBO BOZUIJOH CFZPOE NOFNPOJD TJHOBM
JOH CVU JU JT JOUFOEFE UP CF IFMQGVM

 5IF UZQF PG UIF CJOE XF BSF JNQMFNFOUJOH JT UIF GPMMPX


JOH

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b

5IJT JT UIF JOTUBODF XF BSF EFƶOJOH

 5IJT JT UIF GVODUJPO XFƊSF CJOEJOH PWFS IdentityT m a *U


IBT UIF GPMMPXJOH UZQF

(a -> IdentityT m b)

 )FSF ma JT UIF TBNF POF XF VOQBDLFE PVU PG UIF IdentityT


EBUB DPOTUSVDUPS BOE IBT UIF UZQF m a 3FNPWFE GSPN JUT
*EFOUJUZ5 DPOUFYU UIJT JT OPX UIF m a UIBU UIJT CJOE UBLFT
BT JUT ƶSTU BSHVNFOU

 5IJT JT B EJƵFSFOU CJOE 5IF ƶSTU CJOE JT UIF CJOE XFƊSF


USZJOH UP JNQMFNFOU UIJT CJOE JT JUT EFƶOJUJPO PS JNQMF
NFOUBUJPO 8FƊSF OPX VTJOH UIF .POBE XF BTLFE GPS JO
$)"15&3  & 1-63*#64 .0/"% 

UIF JOTUBODF EFDMBSBUJPO XJUI UIF DPOTUSBJOU Monad m =>


5IJT XJMM IBWF UIF UZQF

(>>=) :: m a -> (a -> m b) -> m b

5IJT JT XJUI SFTQFDU UP UIF Ԝ JO UIF UZQF IdentityT m a OPU


UIF DMBTT PG .POBE JOTUBODFT JO HFOFSBM *O PUIFS XPSET
TJODF XF IBWF BMSFBEZ VOQBDLFE UIF *EFOUJUZ5 CJU BOE JO
B TFOTF HPUUFO JU PVU PG UIF XBZ UIJT CJOE XJMM CF UIF CJOE
GPS UIF UZQF Ԝ JO UIF UZQF IdentityT m 8F EPOƊU LOPX
XIBU .POBE UIBU JT ZFU BOE XF EPOƊU OFFE UP TJODF JU IBT
UIF .POBE UZQFDMBTT DPOTUSBJOU PO UIBU WBSJBCMF XF LOPX
JU BMSFBEZ IBT B .POBE JOTUBODF EFƶOFE GPS JU BOE UIJT
TFDPOE CJOE XJMM CF UIF CJOE EFƶOFE GPS UIBU UZQF "MM
XFƊSF EPJOH IFSF JT EFƶOJOH IPX UP VTF UIBU CJOE JO UIF
QSFTFODF PG UIF BEEJUJPOBM *EFOUJUZ5 TUSVDUVSF

 5IJT JT UIF TBNF ԕ XIJDI XBT BO BSHVNFOU UP UIF .POBE


JOTUBODF XF BSF EFƶOJOH PG UZQF

(a -> IdentityT m b)

 8F OFFE runIdentityT CFDBVTF ԕ SFUVSOT IdentityT m b CVU


UIF >>= GPS UIF Monad m => IBT UIF UZQF m a -> (a -> m b)
-> m b *UƊMM FOE VQ USZJOH UP KPJO m (IdentityT m b) XIJDI
XPOƊU XPSL CFDBVTF m BOE IdentityT m BSF OPU UIF TBNF
UZQF 8F VTF runIdentityT UP VOQBDL UIF WBMVF %PJOH
UIJT IBT UIF UZQF IdentityT m b -> m b BOE UIF DPNQPTJUJPO
$)"15&3  & 1-63*#64 .0/"% 

runIdentityT . f JO UIJT DPOUFYU IBT UIF UZQF a -> m b :PV


DBO VTF undefined JO ()$J UP EFNPOTUSBUF UIJT GPS ZPVSTFMG

Prelude> let f :: (a -> IdentityT m b); f = undefined


Prelude> :t f
f :: a -> IdentityT m b
Prelude> :t runIdentityT
runIdentityT :: IdentityT f a -> f a
Prelude> :t (runIdentityT . f)
(runIdentityT . f) :: a1 -> f a

0, UIF UZQF WBSJBCMFT EPOƊU IBWF UIF TBNF OBNF CVU ZPV
DBO TFF IPX a1 -> f a BOE a -> m b BSF UIF TBNF UZQF

 5P TBUJTGZ UIF UZQF PG UIF PVUFS CJOE XF BSF JNQMFNFOUJOH


GPS UIF .POBE PG IdentityT m XIJDI FYQFDUT B ƶOBM SFTVMU
PG UIF UZQF IdentityT m b XF NVTU UBLF UIF m b XIJDI UIF
FYQSFTTJPO ma >>= runIdentityT . f SFUVSOT BOE SFQBDL JU JO
IdentityT /PUF

Prelude> :t IdentityT
IdentityT :: f a -> IdentityT f a
Prelude> :t runIdentityT
runIdentityT :: IdentityT f a -> f a

/PX XF IBWF B CJOE XF DBO VTF XJUI *EFOUJUZ5 BOE TPNF


PUIFS NPOBE ƈ JO UIJT FYBNQMF B MJTU
$)"15&3  & 1-63*#64 .0/"% 

Prelude> IdentityT [1, 2, 3] >>= (return . (+1))


IdentityT {runIdentityT = [2,3,4]}

*NQMFNFOUJOH UIF CJOE TUFQ CZ TUFQ


/PX XFƊSF HPJOH UP CBDLUSBDL BOE HP UISPVHI JNQMFNFOUJOH
UIBU CJOE TUFQ CZ TUFQ 5IF HPBM IFSF JT UP EFNZTUJGZ XIBU
XFƊWF EPOF BOE FOBCMF ZPV UP XSJUF ZPVS PXO JOTUBODFT GPS
XIBUFWFS NPOBE USBOTGPSNFS ZPV NJHIU OFFE UP JNQMFNFOU
ZPVSTFMG 8FƊMM HP BIFBE BOE TUBSU CBDL BU UIF CFHJOOJOH CVU
XJUI *OTUBODF4JHT UVSOFE PO TP XF DBO TFF UIF UZQF

{-# LANGUAGE InstanceSigs #-}

instance (Monad m) => Monad (IdentityT m) where


return = pure

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
undefined

-FUƊT MFBWF UIF VOEFƶOFE BT PVS ƶOBM SFUVSO FYQSFTTJPO


UIFO VTF let CJOEJOHT BOE DPOUSBEJDUJPO UP TFF UIF UZQFT PG PVS
BUUFNQUT BU NBLJOH B .POBE JOTUBODF 8FƊSF HPJOH UP VTF UIF
$)"15&3  & 1-63*#64 .0/"% 

CPUUPN WBMVF VOEFƶOFE


UP EFGFS UIF QBSUT PG UIF QSPPG XFƊSF
PCMJHBUFE UP QSPEVDF VOUJM XFƊSF SFBEZ 'JSTU MFUƊT KVTU HFU B
let CJOEJOH JO QMBDF BOE TFF JU MPBE FWFO JG UIF DPEF EPFTOƊU
BDUVBMMZ XPSL

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
let aimb = ma >>= f
in undefined

8FƊSF VTJOH ԐԘԜԑ BT B NOFNPOJD GPS UIF QBSUT PG UIF XIPMF


UIJOH UIBU XFƊSF USZJOH UP JNQMFNFOU
)FSF XF HFU BO FSSPS

Couldn't match type ‘m’ with ‘IdentityT m’

5IBU UZQF FSSPS JTOƊU UIF NPTU IFMQGVM UIJOH JO UIF XPSME
*UƊT IBSE UP LOPX XIBUƊT XSPOH GSPN UIBU 4P XFƊMM QPLF BU UIJT
B CJU JO PSEFS UP HFU B NPSF IFMQGVM UZQF FSSPS
'JSTU XFƊMM EP TPNFUIJOH XF LOPX TIPVME XPSL 8FƊMM VTF
fmap JOTUFBE #FDBVTF UIBU XJMM UZQFDIFDL CVU OPU HJWF VT UIF
TBNF SFTVMU BT (>>=)
XF OFFE UP EP TPNFUIJOH UP HJWF UIF
DPNQJMFS B DIBODF UP DPOUSBEJDU VT BOE UFMM VT UIF SFBM UZQF
8F GPSDF UIBU UZQF FSSPS CZ BTTFSUJOH B GVMMZ QPMZNPSQIJD UZQF
GPS ԐԘԜԑ
$)"15&3  & 1-63*#64 .0/"% 

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
let aimb :: a
aimb = fmap f ma
in undefined

5IF UZQF XF KVTU BTTFSUFE GPS ԐԘԜԑ JT JNQPTTJCMF XFƊWF KVTU


TBJE JU DPVME CF FWFSZ UZQF BOE JU DBOƊU 5IF POMZ UIJOH UIBU
DBO IBWF UIBU UZQF JT CPUUPN BT CPUUPN JOIBCJUT BMM UZQFT
$POWFOJFOUMZ ()$ XJMM MFU VT LOPX XIBU ԐԘԜԑ BDUVBMMZ JT

Couldn't match expected type ‘a1’


with actual type ‘m (IdentityT m b)’

8JUI UIF DVSSFOU JNQMFNFOUBUJPO ԐԘԜԑ IBT UIF UZQF m (IdentityT


m b) /PX XF DBO TFF UIF SFBM QSPCMFN UIFSF JT BO *EFOUJUZ5
MBZFS JO CFUXFFO UIF UXP CJUT PG Ԝ UIBU XF OFFE UP KPJO JO PSEFS
UP IBWF B NPOBE
)FSFƊT B CSFBLEPXO
$)"15&3  & 1-63*#64 .0/"% 

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b

-- the pattern match on IdentityT is


-- basically our having lifted over it
-- Problem is, we >>='d

(a -> IdentityT m b)

-- over

m a

-- and got

m (IdentityT m b)

*U EPFTOƊU UZQFDIFDL CFDBVTF (>>=) NFSHFT TUSVDUVSF PG UIF


TBNF UZQF BǒFS MJǒJOH SFNFNCFS JUƊT GNBQ DPNQPTFE XJUI
KPJO VOEFS UIF IPPE
 )BE PVS UZQF CFFO m (m b) BǒFS CJOEJOH
f PWFS ma JU XPVMEƊWF XPSLFE ƶOF "T JU JT XF OFFE UP ƶOE B
XBZ UP HFU UIF UXP CJUT PG Ԝ UPHFUIFS XJUIPVU BO JOUFSWFOJOH
*EFOUJUZ5 MBZFS
8FƊSF HPJOH UP DPOUJOVF XJUI IBWJOH TFQBSBUF fmap BOE join
$)"15&3  & 1-63*#64 .0/"% 

JOTUFBE PG VTJOH (>>=) CFDBVTF JU NBLFT UIF TUFQXJTF NBOJQ


VMBUJPO PG TUSVDUVSF FBTJFS UP TFF )PX EP XF HFU SJE PG UIF
*EFOUJUZ5 JO UIF NJEEMF PG UIF UXP Ԝ TUSVDUVSFT 8FMM XF LOPX
Ԝ JT B .POBE XIJDI NFBOT JUƊT BMTP B 'VODUPS 4P XF DBO VTF
runIdentityT UP HFU SJE PG UIF *EFOUJUZ5 TUSVDUVSF JO UIF NJEEMF
PG UIF TUBDL PG UZQFT

-- Trying to change m (IdentityT m b)


-- into m (m b)

-- Note:
runIdentityT :: IdentityT f a -> f a
fmap runIdentityT :: Functor f => f (IdentityT f1 a) -> f (f1 a)

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
let aimb :: a
aimb = fmap runIdentityT (fmap f ma)
in undefined

"OE XIFO XF MPBE UIJT DPEF XF HFU BO FODPVSBHJOH UZQF


FSSPS

Couldn't match expected type ‘a1’


$)"15&3  & 1-63*#64 .0/"% 

with actual type ‘m (m b)’

*UƊT UFMMJOH VT XF IBWF BDIJFWFE UIF UZQF m (m b) TP OPX XF


LOPX IPX UP HFU XIFSF XF XBOU 5IF Ԑ IFSF JT UIF Ԑ XF IBE
BTTJHOFE UP ԐԘԜԑ CVU JUƊT UFMMJOH VT UIBU PVS BDUVBM UZQF JT OPU
XIBU XF BTTFSUFE CVU UIJT PUIFS UZQF 5IVT XF IBWF EJTDPWFSFE
XIBU PVS BDUVBM UZQF JT XIJDI HJWFT VT B DMVF BCPVU IPX UP ƶY
JU
8FƊMM VTF join GSPN Control.Monad UP NFSHF UIF OFTUFE Ԝ
TUSVDUVSF

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
let aimb :: a
aimb = join (fmap runIdentityT (fmap f ma))
in undefined

"OE XIFO XF MPBE JU UIF DPNQJMFS UFMMT VT XF ƶOBMMZ IBWF


BO m b XIJDI XF DBO SFUVSO

Couldn't match expected type ‘a1’


with actual type ‘m b’

*O GBDU CFGPSF XF CFHJO DMFBOJOH VQ PVS DPEF XF DBO WFSJGZ


UIJT JT UIF DBTF SFBM RVJDL
$)"15&3  & 1-63*#64 .0/"% 

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
let aimb = join (fmap runIdentityT (fmap f ma))
in aimb

8F SFNPWFE UIF UZQF EFDMBSBUJPO GPS aimb BOE BMTP DIBOHFE


UIF in undefined #VU XF LOPX UIBU ԐԘԜԑ IBT UIF BDUVBM UZQF m
b TP UIJT XPOƊU XPSL 8IZ *G XF UBLF B MPPL BU UIF UZQF FSSPS

Couldn't match type ‘m’ with ‘IdentityT m’

5IF (>>=) XF BSF JNQMFNFOUJOH IBT B ƶOBM SFTVMU PG UZQF


IdentityT m b TP UIF UZQF PG ԐԘԜԑ EPFTOƊU NBUDI JU ZFU 8F OFFE
UP XSBQ m b JO *EFOUJUZ5 UP NBLF JU UZQFDIFDL
$)"15&3  & 1-63*#64 .0/"% 

-- Remember:
IdentityT :: f a -> IdentityT f a

instance (Monad m) => Monad (IdentityT m) where


return = pure

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
let aimb = join (fmap runIdentityT (fmap f ma))
in IdentityT aimb

5IJT TIPVME DPNQJMF 8F SFXSBQ m b CBDL JO UIF IdentityT


UZQF BOE XF TIPVME CF HPPE UP HP

3FGBDUPSJOH
/PX UIBU XF IBWF TPNFUIJOH UIBU XPSLT MFUƊT SFGBDUPS 8FƊE
MJLF UP JNQSPWF PVS JNQMFNFOUBUJPO PG (>>=) 5BLJOH UIJOHT
POF TUFQ BU B UJNF JT VTVBMMZ NPSF TVDDFTTGVM UIBO USZJOH UP
SFXSJUF BMM BU PODF FTQFDJBMMZ PODF ZPV IBWF B CBTFMJOF WFSTJPO
UIBU ZPV LOPX TIPVME XPSL )PX TIPVME XF JNQSPWF UIJT MJOF

IdentityT $ join (fmap runIdentityT (fmap f ma))


$)"15&3  & 1-63*#64 .0/"% 

8FMM POF PG UIF 'VODUPS MBXT UFMMT VT TPNFUIJOH BCPVU GNBQ


QJOH UXJDF

-- Functor law:
fmap (f . g) == fmap f . fmap g

*OEFFE 4P XF DBO DIBOHF UIBU MJOF UP UIF GPMMPXJOH BOE JU


TIPVME CF JEFOUJDBM

IdentityT $ join (fmap (runIdentityT . f) ma)

/PX JU TFFNT TVTQJDJPVT UIBU XFƊSF GNBQQJOH BOE BMTP VTJOH


join PO UIF SFTVMU PG IBWJOH GNBQQFE UIF UXP GVODUJPOT XF
DPNQPTFE *TOƊU join DPNQPTFE XJUI fmap KVTU (>>=)

x >>= f = join (fmap f x)

"DDPSEJOHMZ XF DBO DIBOHF PVS .POBE JOTUBODF UP UIF


GPMMPXJOH

instance (Monad m) => Monad (IdentityT m) where


return = pure

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
IdentityT $ ma >>= runIdentityT . f
$)"15&3  & 1-63*#64 .0/"% 

"OE UIBU TIPVME XPSL TUJMM 8F IBWF B UZQF DPOTUSVDUPS OPX


*EFOUJUZ5
UIBU UBLFT B NPOBE BT BO BSHVNFOU BOE SFUVSOT B
NPOBE BT B SFTVMU
5IJT JNQMFNFOUBUJPO DBO CF XSJUUFO PUIFS XBZT *O UIF
transformers MJCSBSZ GPS FYBNQMF JUƊT XSJUUFO MJLF UIJT

m >>= k = IdentityT $ runIdentityT . k =<< runIdentityT m

5BLF B NPNFOU BOE XPSL PVU GPS ZPVSTFMG IPX UIBU JT GVOD
UJPOBMMZ FRVJWBMFOU UP PVS JNQMFNFOUBUJPO

5IF FTTFOUJBM FYUSB PG .POBE USBOTGPSNFST


*U NBZ OPU TFFN MJLF JU CVU UIF *EFOUJUZ5 NPOBE USBOTGPSNFS
BDUVBMMZ DBQUVSFT UIF FTTFODF PG USBOTGPSNFST HFOFSBMMZ 8F
POMZ FNCBSLFE PO UIJT RVFTU CFDBVTF XF DPVMEOƊU CF HVBSBO
UFFE B .POBE JOTUBODF HJWFO UIF DPNQPTJUJPO PG UXP UZQFT
(JWFO UIBU XF LOPX IBWJOH 'VODUPS"QQMJDBUJWF.POBE BU
PVS EJTQPTBM JTOƊU FOPVHI UP NBLF UIBU OFX .POBE JOTUBODF
4P XIBU XBT OPWFM JO UIF GPMMPXJOH DPEF

(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
IdentityT $ ma >>= runIdentityT . f
$)"15&3  & 1-63*#64 .0/"% 

8FMM JU XBTOƊU UIF QBUUFSO NBUDI PO IdentityT XF HFU UIBU


GSPN UIF 'VODUPS BOZXBZ

-- Not this
(IdentityT ma) ...

*U XBTOƊU UIF BCJMJUZ UP (>>=) GVODUJPOT PWFS UIF ma WBMVF PG


UZQF ԜԐ XF HFU UIBU GSPN UIF .POBE DPOTUSBJOU PO Ԝ BOZXBZ

-- Not this
... ma >>= ...

8F OFFEFE UP LOPX POF PG UIF UZQFT DPODSFUFMZ TP UIBU


XF DPVME VTF runIdentityT FTTFOUJBMMZ GNBQQJOH B GPME PG UIF
*EFOUJUZ5 TUSVDUVSF
BOE UIFO SFQBDL UIF WBMVF JO *EFOUJUZ5

-- We needed to know IdentityT


-- concretely to be able to do this
IdentityT .. runIdentityT ...

"T ZPVƊMM SFDBMM VOUJM XF VTFE runIdentityT XF DPVMEOƊU HFU


UIF UZQFT UP ƶU CFDBVTF IdentityT XBT XFEHFE JO UIF NJEEMF PG
UXP CJUT PG Ԝ *U UVSOT PVU UP CF JNQPTTJCMF UP ƶY UIBU VTJOH
POMZ 'VODUPS "QQMJDBUJWF BOE .POBE 5IJT JT BO FYBNQMF PG
XIZ XF DBOƊU KVTU NBLF B .POBE JOTUBODF GPS UIF $PNQPTF
UZQF CVU XF DBO NBLF B USBOTGPSNFS UZQF MJLF IdentityT XIFSF
XF MFWFSBHF JOGPSNBUJPO TQFDJƶD UP UIF UZQF BOE DPNCJOF JU
$)"15&3  & 1-63*#64 .0/"% 

XJUI BOZ PUIFS UZQF UIBU IBT B .POBE JOTUBODF *O HFOFSBM JO


PSEFS UP NBLF UIF UZQFT ƶU XFƊMM OFFE TPNF XBZ UP GPME BOE
SFDPOTUSVDU UIF UZQF XF IBWF DPODSFUF JOGPSNBUJPO GPS

 'JOEJOH B QBUUFSO


5SBOTGPSNFST BSF CFBSFST PG TJOHMFUZQF DPODSFUF JOGPSNBUJPO
UIBU MFU ZPV DSFBUF FWFSCJHHFS .POBET JO B TFOTF /FTUJOH
TVDI BT

(Monad m) => m (m a)

JT BEESFTTFE CZ join BMSFBEZ 8F VTF USBOTGPSNFST XIFO


XF XBOU B >>= PQFSBUJPO PWFS ԕ BOE Ԗ PG EJƵFSFOU UZQFT CVU
CPUI IBWF .POBE JOTUBODFT
 :PV IBWF UP DSFBUF OFX UZQFT
DBMMFE NPOBE USBOTGPSNFST BOE XSJUF .POBE JOTUBODFT GPS
UIPTF UZQFT UP IBWF B XBZ PG EFBMJOH XJUI UIF FYUSB TUSVDUVSF
HFOFSBUFE
5IF HFOFSBM QBUUFSO JT UIJT :PV XBOU UP DPNQPTF UXP QPMZ
NPSQIJD UZQFT ԕ BOE Ԗ UIBU FBDI IBWF B .POBE JOTUBODF #VU
ZPVƊMM FOE VQ XJUI UIJT QBUUFSO

f (g (f b))

.POBEƊT CJOE DBOƊU KPJO UIPTF UZQFT OPU XJUI UIBU JOUFSWFO
JOH Ԗ 4P ZPV OFFE UP HFU UP UIJT
$)"15&3  & 1-63*#64 .0/"% 

f (f b)

:PV XPOƊU CF BCMF UP VOMFTT ZPV IBWF TPNF XBZ PG GPMEJOH UIF
Ԗ JO UIF NJEEMF :PV DBOƊU EP UIBU XJUI KVTU .POBE 5IF FTTFODF
PG .POBE JT join CVU IFSF ZPV IBWF POMZ POF CJU PG Ԗ TUSVDUVSF
OPU g (g ...) TP UIBUƊT OPU FOPVHI 5IF TUSBJHIUGPSXBSE UIJOH
UP EP JT UP NBLF Ԗ DPODSFUF 8JUI DPODSFUF UZQF JOGPSNBUJPO
GPS UIF ƌJOOFSƍ CJU PG TUSVDUVSF XF DBO GPME PVU UIF Ԗ BOE HFU
PO XJUI JU 5IF HPPE OFXT JT UIBU USBOTGPSNFST EPOƊU SFRVJSF
ԕ CF DPODSFUF ԕ DBO SFNBJO QPMZNPSQIJD TP MPOH BT JU IBT B
.POBE JOTUBODF TP XF POMZ XSJUF B USBOTGPSNFS PODF GPS FBDI
UZQF
8F DBO TFF UIJT QBUUFSO XJUI *EFOUJUZ5 BT XFMM :PV NBZ
SFDBMM UIJT TUFQ JO PVS QSPDFTT PG XSJUJOH *EFOUJUZ5ƊT .POBE

(IdentityT ma) >>= f =


let aimb :: m (IdentityT m b)
aimb = fmap f ma

8F IBWF TPNFUIJOH UIBUƊMM UZQFDIFDL CVU JUƊT OPU RVJUF JO UIF


TIBQF XF XPVME MJLF 0G DPVSTF UIF VOEFSMZJOH UZQF PODF XF
UISPX BXBZ UIF *EFOUJUZ5 EBUB DPOTUSVDUPS JT m (m b) XIJDIƊMM
TVJU VT KVTU ƶOF CVU XF IBWF UP GPME PVU UIF *EFOUJUZ5 CFGPSF XF
DBO VTF UIF join GSPN Monad m => m 5IBU MFBET VT UP UIF OFYU
TUFQ
$)"15&3  & 1-63*#64 .0/"% 

let aimb :: m (m b)
aimb = fmap runIdentityT (fmap f ma)

/PX XF ƶOBMMZ IBWF TPNFUIJOH XF DBO KPJO CFDBVTF XF MJǒFE


UIF SFDPSE BDDFTTPS GPS *EFOUJUZ5 PWFS UIF Ԝ 4JODF *EFOUJUZ5
JT TP TJNQMF UIF SFDPSE BDDFTTPS JT TVƸDJFOU UP ƌGPME BXBZƍ UIF
TUSVDUVSF 'SPN UIFSF UIF GPMMPXJOH USBOTJUJPOT CFDPNF FBTZ

m (m b) -> m b -> IdentityT m b

5IF ƶOBM UZQF JT XIBU PVS EFƶOJUJPO PG (>>=) GPS *EFOUJUZ5


NVTU SFTVMU JO
5IF CBTJD QBUUFSO UIBU NBOZ NPOBE USBOTGPSNFST BSF FO
BCMJOH VT UP DPQF XJUI JT UIF GPMMPXJOH UZQF USBOTJUJPOT XIFSF
Ԝ JT UIF QPMZNPSQIJD ƌPVUFSƍ TUSVDUVSF BOE ԉ JT TPNF DPO
DSFUF UZQF UIF USBOTGPSNFS JT GPS 'PS FYBNQMF JO UIF BCPWF ԉ
XPVME CF *EFOUJUZ5

m (T m b)
-> m (m b)
-> m b
-> T m b

%POƊU DPOTJEFS UIJT B IBSE BOE GBTU SVMF GPS XIBU UZQFT ZPVƊMM
FODPVOUFS JO JNQMFNFOUJOH USBOTGPSNFST CVU SBUIFS TPNF
JOUVJUJPO GPS XIZ USBOTGPSNFST BSF OFDFTTBSZ UP CFHJO XJUI
$IBQUFS 

.POBE USBOTGPSNFST

+F OF EJT DFT DIPTFT RVF


EBOT MB NFTVSF P¹ KF
DPOTJE¨SF RVF DFMB
QFSNFU EF MFT
USBOTGPSNFS

.JDIFM 'PVDBVMU


$)"15&3  45"$, Ɖ&. 61 

 .POBE USBOTGPSNFST


5IF MBTU DIBQUFS EFNPOTUSBUFE XIZ XF OFFE NPOBE USBOTGPSN
FST BOE UIF CBTJD UZQF NBOJQVMBUJPO UIBUƊT HPJOH PO UP NBLF
UIBU CJU PƊ NBHJDL IBQQFO .POBE USBOTGPSNFST BSF JNQPSUBOU
JO B MPU PG FWFSZEBZ )BTLFMM DPEF UIPVHI TP XF XBOU UP EJWF
EFFQFS BOE NBLF TVSF XF IBWF B HPPE VOEFSTUBOEJOH PG IPX
UP VTF UIFN JO QSBDUJDF &WFO BǒFS ZPV LOPX IPX UP XSJUF BMM
UIF USBOTGPSNFS JOTUBODFT NBOBHJOH TUBDLT PG USBOTGPSNFST
JO BO BQQMJDBUJPO DBO CF USJDLZ 5IF HPBM PG UIJT DIBQUFS JT UP
HFU DPNGPSUBCMF XJUI JU
*O UIJT DIBQUFS XF XJMM

Ƒ XPSL UISPVHI NPSF NPOBE USBOTGPSNFS UZQFT BOE JO


TUBODFT

Ƒ MPPL BU UIF PSEFSJOH BOE XSBQQJOH PG NPOBE USBOTGPSNFS


TUBDLT

Ƒ MJǒ MJǒ MJǒ BOE MJǒ TPNF NPSF

 .BZCF5
*O UIF MBTU DIBQUFS XF XPSLFE UISPVHI BO FYUFOEFE CSFBLEPXO
PG UIF *EFOUJUZ5 USBOTGPSNFS *EFOUJUZ5 JT BT ZPV NJHIU JNBH
JOF OPU UIF NPTU VTFGVM PG UIF NPOBE USBOTGPSNFST BMUIPVHI
JU JT OPU XJUIPVU QSBDUJDBM BQQMJDBUJPOT NPSF PO UIJT MBUFS
 "T
$)"15&3  45"$, Ɖ&. 61 

XFƊWF TFFO BU WBSJPVT UJNFT UIPVHI UIF .BZCF .POBE DBO


CF FYUSFNFMZ VTFGVM BOE TP JU JT UIBU UIF USBOGPSNFS WBSJBOU
.BZCF5 ƶOET JUT XBZ JOUP UIF QBOUIFPO PG JNQPSUBOU USBOT
GPSNFST
5IF .BZCF5 USBOTGPSNFS JT B CJU NPSF DPNQMFY UIBO *EFO
UJUZ5 *G ZPV XPSLFE UISPVHI BMM UIF FYFSDJTFT PG UIF QSFWJPVT
DIBQUFS UIFO UIJT TFDUJPO XJMM OPU CF UPP TVSQSJTJOH CFDBVTF
UIJT XJMM SFMZ PO UIJOHT ZPVƊWF TFFO XJUI *EFOUJUZ5 BOE UIF $PN
QPTF UZQF BMSFBEZ )PXFWFS UP FOTVSF UIBU USBOTGPSNFST BSF
UIPSPVHIMZ EFNZTUJƶFE GPS ZPV JUƊT XPSUI XPSLJOH UISPVHI
UIFN DBSFGVMMZ
8F CFHJO XJUI UIF OFXUZQF GPS PVS USBOTGPSNFS

newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a) }

5IF TUSVDUVSF PG PVS .BZCF5 UZQF BOE UIF $PNQPTF UZQF


BSF TJNJMBS TP XF DBO SFVTF UIF CBTJD QBUUFSOT PG UIF $PNQPTF
UZQF GPS UIF 'VODUPS BOE "QQMJDBUJWF JOTUBODFT
$)"15&3  45"$, Ɖ&. 61 

-- Remember the Functor for Compose?

instance (Functor f, Functor g) =>


Functor (Compose f g) where
fmap f (Compose fga) =
Compose $ (fmap . fmap) f fga

-- compare to the instance for MaybeT


instance (Functor m) => Functor (MaybeT m) where
fmap f (MaybeT ma) =
MaybeT $ (fmap . fmap) f ma

8F EPOƊU OFFE UP EP BOZUIJOH EJƵFSFOU GPS UIF 'VODUPS


JOTUBODF CFDBVTF USBOTGPSNFST BSF OFFEFE GPS UIF .POBE OPU
UIF 'VODUPS

4QPJMFS BMFSU
*G ZPV IBWFOƊU ZFU XSJUUFO UIF "QQMJDBUJWF JOTUBODF GPS $PNQPTF
GSPN UIF QSFWJPVT DIBQUFS ZPV NBZ XBOU UP TUPQ SJHIU IFSF
*G ZPV XFSF TUVDL PO JU BOE GSVTUSBUFE CZ JU UIFSF JT B IJOU JO
UIF BOTXFST TFDUJPO PG UIF QSFWJPVT DIBQUFS BOE ZPV NBZ XBOU
UP MPPL BU UIBU OPX CFGPSF SFBEJOH UIJT TFDUJPO 0S KVTU KVNQ
SJHIU JO ƈ XF KVTU XBOUFE UP XBSO ZPV BT UIJT TFDUJPO NBZ SVJO
UIBU FYFSDJTF GPS ZPV JG ZPV IBWFOƊU EPOF JU ZFU
$)"15&3  45"$, Ɖ&. 61 

8FƊMM TUBSU XJUI XIBU NJHIU TFFN MJLF BO PCWJPVT XBZ UP


XSJUF UIF .BZCF5 "QQMJDBUJWF BOE ƶOE PVU XIZ JU EPFTOƊU XPSL
5IJT EPFT OPU DPNQJMF

instance (Applicative m) => Applicative (MaybeT m) where


pure x = MaybeT (pure (pure x))

(MaybeT fab) <*> (MaybeT mma) =


MaybeT $ fab <*> mma

5IF ԕԐԑ SFQSFTFOUT UIF GVODUJPO m (Maybe (a -> b)) BOE UIF
ԜԜԐ SFQSFTFOUT UIF m (Maybe a)
:PVƊMM HFU UIJT FSSPS JG ZPV USZ JU

Couldn't match type ‘Maybe (a -> b)’


with ‘Maybe a -> Maybe b’

)FSF JT UIF "QQMJDBUJWF JOTUBODF GPS $PNQPTF BT B DPNQBSJ


TPO XJUI UIF .BZCF5 JOTUBODF XFƊSF USZJOH UP XSJUF

instance (Applicative f, Applicative g) =>


Applicative (Compose f g) where
pure x = Compose (pure (pure x))
Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)

-FUƊT CSFBL UIJT EPXO B CJU JO DBTF ZPV GFMU DPOGVTFE XIFO
ZPV XSPUF UIJT GPS UIF MBTU DIBQUFSƊT FYFSDJTF #FDBVTF ZPV EJE
UIBU FYFSDJTFƒSJHIU
$)"15&3  45"$, Ɖ&. 61 

5IF JEFB IFSF JT UIBU XF IBWF UP MJǒ BO "QQMJDBUJWF ƌBQQMZƍ


PWFS UIF PVUFS TUSVDUVSF ԕ UP HFU UIF g (a -> b) JOUP g a -> g b
TP UIBU UIF "QQMJDBUJWF JOTUBODF GPS ԕ DBO CF MFWFSBHFE 8F DBO
TUSFUDI UIJT JEFB B CJU BOE VTF DPODSFUF UZQFT

innerMost :: [Maybe (Identity (a -> b))]


-> [Maybe (Identity a -> Identity b)]
innerMost = (fmap . fmap) (<*>)

second' :: [Maybe (Identity a -> Identity b)]


-> [Maybe (Identity a) -> Maybe (Identity b)]
second' = fmap (<*>)

final' :: [Maybe (Identity a) -> Maybe (Identity b)]


-> [Maybe (Identity a)] -> [Maybe (Identity b)]
final' = (<*>)

5IF GVODUJPO UIBU DPVME CF UIF BDUVBM "QQMJDBUJWF JOTUBODF


GPS TVDI B IZQPUIFUJDBM UZQF XPVME MPPL MJLF

lmiApply :: [Maybe (Identity (a -> b))]


-> [Maybe (Identity a)]
-> [Maybe (Identity b)]
lmiApply f x =
final' (second' (innerMost f)) x
$)"15&3  45"$, Ɖ&. 61 

5IF "QQMJDBUJWF JOTUBODF GPS PVS .BZCF5 UZQF XJMM FNQMPZ


UIJT TBNF JEFB CFDBVTF "QQMJDBUJWFT BSF DMPTFE VOEFS DPN
QPTJUJPO BT XF OPUFE JO UIF MBTU DIBQUFS 8F POMZ OFFE UP EP
TPNFUIJOH EJƵFSFOU GSPN UIF $PNQPTF JOTUBODFT PODF XF HFU
UP .POBE
4P XF UPPL UIF MPOH XBZ BSPVOE UP UIJT

instance (Applicative m) => Applicative (MaybeT m) where


pure x = MaybeT (pure (pure x))

(MaybeT fab) <*> (MaybeT mma) =


MaybeT $ (<*>) <$> fab <*> mma

.BZCF5 .POBE JOTUBODF


"U MBTU PO UP UIF .POBE JOTUBODF /PUF UIBU XFƊWF HJWFO TPNF
PG UIF JOUFSNFEJBUF UZQFT
$)"15&3  45"$, Ɖ&. 61 

instance (Monad m) => Monad (MaybeT m) where


return = pure

(>>=) :: MaybeT m a
-> (a -> MaybeT m b)
-> MaybeT m b
(MaybeT ma) >>= f =
-- [2] [3]
MaybeT $ do
-- [ 1 ]
-- ma :: m (Maybe a)
-- v :: Maybe a
v <- ma
-- [4]
case v of
-- [5]
Nothing -> return Nothing
-- [ 6 ]
-- y :: a
-- f :: a -> MaybeT m b
-- f y :: MaybeT m b
-- runMaybeT (f y) :: m b
Just y -> runMaybeT (f y)
-- [7] [8]
$)"15&3  45"$, Ɖ&. 61 

&YQMBJOJOH JU TUFQ CZ TUFQ

 8F IBWF UP SFUVSO B .BZCF5 WBMVF BU UIF FOE TP UIF do


CMPDL IBT UIF .BZCF5 EBUB DPOTUSVDUPS JO GSPOU PG JU 5IJT
NFBOT UIF ƶOBM WBMVF PG PVS doCMPDL FYQSFTTJPO NVTU CF
PG UZQF m b JO PSEFS UP UZQFDIFDL CFDBVTF PVS HPBM JT UP
HP GSPN MaybeT m a UP MaybeT m b

 5IF ƶSTU BSHVNFOU UP CJOE IFSF JT MaybeT m a 8F VO


CVOEMFE UIBU GSPN .BZCF5 CZ QBUUFSO NBUDIJOH PO UIF
.BZCF5 OFXUZQF EBUB DPOTUSVDUPS

 5IF TFDPOE BSHVNFOU UP CJOE JT (a -> MaybeT m b)

 *O UIF EFƶOJUJPO PG .BZCF5 OPUJDF TPNFUIJOH

newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a) }
-- ^---------^

*UƊT B .BZCF WBMVF XSBQQFE JO TPNF PUIFS UZQF GPS XIJDI BMM
XF LOPX JT UIBU JU IBT B .POBE JOTUBODF "DDPSEJOHMZ XF
CFHJO JO PVS doCMPDL CZ VTJOH UIF MFǒ BSSPX CJOE TZOUBY
5IJT HJWFT VT B SFGFSFODF UP UIF IZQPUIFUJDBM .BZCF WBMVF
PVU PG UIF Ԝ TUSVDUVSF XIJDI JT VOLOPXO

 4JODF VTJOH <- UP CJOE Maybe a PVU PG m (Maybe a) MFǒ VT


XJUI B .BZCF WBMVF XF EP B QMBJO PME DBTF FYQSFTTJPO PO
UIF .BZCF WBMVF
$)"15&3  45"$, Ɖ&. 61 

 *G XF HFU /PUIJOH XF LJDL /PUIJOH CBDL PVU CVU XF IBWF


UP SFFNCFE JU JO UIF Ԝ TUSVDUVSF 8F EPOƊU LOPX XIBU Ԝ
JT CVU CFJOH B .POBE BOE UIVT BMTP BO "QQMJDBUJWF
NFBOT
XF DBO VTF return pure
UP QFSGPSN UIBU FNCFEEJOH

 *G XF HFU +VTU XF OPX IBWF B WBMVF PG UZQF Ԑ UIBU XF DBO


QBTT UP PVS GVODUJPO f PG UZQF a -> MaybeT m b

 8F IBWF UP GPME UIF m b WBMVF PVU PG UIF .BZCF5 TJODF


UIF .BZCF5 DPOTUSVDUPS JT BMSFBEZ XSBQQFE BSPVOE UIF
XIPMF doCMPDL UIFO XFƊSF EPOF

%POƊU CF BGSBJE UP HFU B QFO BOE QBQFS BOE XPSL BMM UIBU PVU
VOUJM ZPV SFBMMZ VOEFSTUBOE IPX UIJOHT BSF IBQQFOJOH CFGPSF
ZPV NPWF PO

 &JUIFS5
+VTU BT .BZCF IBT B USBOTGPSNFS WBSJBOU JO UIF GPSN PG .BZ
CF5 XF DBO NBLF B USBOTGPSNFS WBSJBOU PG &JUIFS 8FƊMM DBMM
JU &JUIFS5 :PVS UBTL JT UP JNQMFNFOU UIF JOTUBODFT GPS UIF
USBOTGPSNFS WBSJBOU

newtype EitherT e m a =
EitherT { runEitherT :: m (Either e a) }
$)"15&3  45"$, Ɖ&. 61 

&YFSDJTFT &JUIFS5
 8SJUF UIF 'VODUPS JOTUBODF GPS &JUIFS5

instance Functor m => Functor (EitherT e m) where


fmap = undefined

 8SJUF UIF "QQMJDBUJWF JOTUBODF GPS &JUIFS5

instance Applicative m => Applicative (EitherT e m) where


pure = undefined

f <*> a = undefined

 8SJUF UIF .POBE JOTUBODF GPS &JUIFS5

instance Monad m => Monad (EitherT e m) where


return = pure

v >>= f = undefined

 8SJUF UIF swapEitherT IFMQFS GVODUJPO GPS &JUIFS5

-- transformer version of swapEither.


swapEitherT :: (Functor m) => EitherT e m a -> EitherT a m e
swapEitherT = undefined

)JOU XSJUF swapEither ƶSTU UIFO swapEitherT JO UFSNT PG


UIF GPSNFS
$)"15&3  45"$, Ɖ&. 61 

 8SJUF UIF USBOTGPSNFS WBSJBOU PG UIF either DBUBNPSQIJTN

eitherT :: Monad m =>


(a -> m c)
-> (b -> m c)
-> EitherT a m b
-> m c
eitherT = undefined

 3FBEFS5
8F NFOUJPOFE CBDL JO UIF 3FBEFS DIBQUFS UIBU BDUVBMMZ ZPV
NPSF PǒFO TFF 3FBEFS5 UIBO 3FBEFS JO DPNNPO )BTLFMM VTF
3FBEFS5 JT POF PG UIF NPTU DPNNPOMZ VTFE USBOTGPSNFST
JO DPOWFOUJPOBM )BTLFMM BQQMJDBUJPOT *U JT KVTU MJLF 3FBEFS
FYDFQU JO UIF USBOTGPSNFS WBSJBOU XFƊSF HFOFSBUJOH BEEJUJPOBM
TUSVDUVSF JO UIF SFUVSO UZQF PG UIF GVODUJPO

newtype ReaderT r m a =
ReaderT { runReaderT :: r -> m a }

5IF WBMVF JOTJEF UIF 3FBEFS5 JT B GVODUJPO 5ZQF DPOTUSVD


UPST TVDI BT .BZCF BSF BMTP GVODUJPOT JO TPNF TFOTFT CVU XF
IBWF UP IBOEMF UIJT DBTF B CJU EJƵFSFOUMZ 5IF ƶSTU BSHVNFOU UP
UIF GVODUJPO JOTJEF 3FBEFS5 JT QBSU PG UIF TUSVDUVSF XFƊMM IBWF
UP CJOE PWFS
$)"15&3  45"$, Ɖ&. 61 

5IJT UJNF XFƊSF HPJOH UP HJWF ZPV UIF JOTUBODFT *G ZPV XBOU
UP USZ XSJUJOH UIFN ZPVSTFMG EP OPU SFBE PO
$)"15&3  45"$, Ɖ&. 61 

instance (Functor m) => Functor (ReaderT r m) where


fmap f (ReaderT rma) =
ReaderT $ (fmap . fmap) f rma

instance (Applicative m) => Applicative (ReaderT r m) where


pure a = ReaderT (pure (pure a))

(ReaderT fmab) <*> (ReaderT rma) =


ReaderT $ (<*>) <$> fmab <*> rma

instance (Monad m) => Monad (ReaderT r m) where


return = pure

(>>=) :: ReaderT r m a
-> (a -> ReaderT r m b)
-> ReaderT r m b
(ReaderT rma) >>= f =
ReaderT $ \r -> do
-- [1]
a <- rma r
-- [3] [ 2 ]
runReaderT (f a) r
-- [5] [ 4 ] [6]

 "HBJO UIF UZQF PG UIF WBMVF JO B 3FBEFS5 NVTU CF B GVOD


$)"15&3  45"$, Ɖ&. 61 

UJPO TP UIF BDU PG CJOEJOH B GVODUJPO PWFS B 3FBEFS5 NVTU


JUTFMG CF B GVODUJPO BXBJUJOH UIF BSHVNFOU PG UZQF ԡ XIJDI
XFƊWF DIPTFO UP OBNF ԡ BT B DPOWFOJFODF JO PVS UFSNT
"MTP OPUF UIBU XFƊSF SFQBDLJOH PVS MBNCEB JOTJEF UIF 3FBE
FS5 EBUB DPOTUSVDUPS

 8F QBUUFSONBUDIFE UIF r -> m a SFQSFTFOUFE JO PVS UFSNT


CZ ԡԜԐ
PVU PG UIF 3FBEFS5 EBUB DPOTUSVDUPS /PX XFƊSF
BQQMZJOH JU UP UIF ԡ UIBU XFƊSF FYQFDUJOH JO UIF CPEZ PG UIF
BOPOZNPVT MBNCEB

 5IF SFTVMU PG BQQMZJOH r -> m a UP B WBMVF PG UZQF ԡ JT m


a 8F OFFE B WBMVF PG UZQF Ԑ JO PSEFS UP BQQMZ PVS a ->
ReaderT r m b GVODUJPO 5P CF BCMF UP XSJUF DPEF JO UFSNT
PG UIBU IZQPUIFUJDBM Ԑ XF CJOE <-
UIF Ԑ PVU PG UIF Ԝ
TUSVDUVSF 8FƊWF CPVOE UIBU WBMVF UP UIF OBNF Ԑ BT B
NOFNPOJD UP SFNFNCFS UIF UZQF

 "QQMZJOH ԕ XIJDI IBT UZQF a -> ReaderT r m b UP UIF WBMVF


Ԑ SFTVMUT JO B WBMVF PG UZQF ReaderT r m b

 8F VOQBDL UIF r -> m b PVU PG UIF 3FBEFS5 TUSVDUVSF

 'JOBMMZ XF BQQMZ UIF SFTVMUJOH r -> m b UP UIF ԡ XF IBE BU


UIF CFHJOOJOH PG PVS MBNCEB UIBU FWFOUVBM BSHVNFOU UIBU
3FBEFS BCTUSBDUT GPS VT 8F IBWF UP SFUVSO m b BT UIF ƶOBM
FYQSFTTJPO JO UIJT BOPOZNPVT MBNCEB PS UIF GVODUJPO JT
OPU WBMJE 5P CF WBMJE JU NVTU CF PG UZQF r -> m b XIJDI
$)"15&3  45"$, Ɖ&. 61 

FYQSFTTFT UIF DPOTUSBJOU UIBU JG JU JT BQQMJFE UP BO BSHVNFOU


PG UZQF ԡ JU NVTU QSPEVDF B WBMVF PG UZQF m b

/P FYFSDJTFT UIJT UJNF :PV EFTFSWF B CSFBL

 4UBUF5
4JNJMBS UP 3FBEFS BOE 3FBEFS5 4UBUF5 JT 4UBUF CVU XJUI BEEJ
UJPOBM NPOBEJD TUSVDUVSF XSBQQFE BSPVOE UIF SFTVMU 4UBUF5
JT TPNFXIBU NPSF VTFGVM BOE DPNNPO UIBO UIF 4UBUF .POBE
ZPV TBX FBSMJFS -JLF 3FBEFS5 JUT WBMVF JT B GVODUJPO

newtype StateT s m a =
StateT { runStateT :: s -> m (a,s) }

&YFSDJTFT 4UBUF5
*G ZPVƊSF GBNJMJBS XJUI UIF EJTUJODUJPO ZPVƊMM CF JNQMFNFOUJOH
UIF TUSJDU WBSJBOU PG 4UBUF5 IFSF 5P NBLF UIF TUSJDU WBSJBOU ZPV
EPOƊU IBWF UP EP BOZUIJOH TQFDJBM +VTU XSJUF UIF NPTU PCWJPVT
UIJOH UIBU DPVME XPSL 5IF MB[Z MB[JFS BOZXBZ
WBSJBOU JT
UIF POF UIBU JOWPMWFT BEEJOH B CJU FYUSB 8FƊMM FYQMBJO UIF
EJƵFSFODF JO UIF DIBQUFS PO OPOTUSJDUOFTT

 :PVƊMM IBWF UP EP UIF 'VODUPS BOE "QQMJDBUJWF JOTUBODFT


ƶSTU CFDBVTF UIFSF BSFOƊU 'VODUPS BOE "QQMJDBUJWF JO
TUBODFT SFBEZ UP HP GPS UIF UZQF Monad m => s -> m (a, s)
$)"15&3  45"$, Ɖ&. 61 

instance (Functor m) => Functor (StateT s m) where


fmap f m = undefined

 "T XJUI 'VODUPS ZPV DBOƊU DIFBU BOE SFVTF BO VOEFSMZJOH


"QQMJDBUJWF JOTUBODF TP ZPVƊMM IBWF UP EP UIF XPSL XJUI
UIF s -> m (a, s) UZQF ZPVSTFMG

instance (Monad m) => Applicative (StateT s m) where


pure = undefined
(<*>) = undefined

"MTP OPUF UIBU UIF DPOTUSBJOU PO Ԝ JT OPU "QQMJDBUJWF BT


ZPV FYQFDU CVU SBUIFS .POBE 5IJT JT CFDBVTF ZPV DBOƊU
FYQSFTT UIF PSEFSEFQFOEFOU DPNQVUBUJPO ZPVƊE FYQFDU
UIF 4UBUF5 "QQMJDBUJWF UP IBWF XJUIPVU IBWJOH B .POBE
GPS Ԝ 5P MFBSO NPSF TFF UIJT 4UBDL 0WFSƷPX RVFTUJPO
BCPVU UIJT JTTVF "MTP TFF UIJT (JUIVC JTTVF PO UIF /*$5"
$PVSTF (JUIVC SFQPTJUPSZ #FXBSF 5IF /*$5" DPVSTF
JTTVF HJWFT BXBZ UIF BOTXFS *O FTTFODF UIF JTTVF JT UIBU
XJUIPVU .POBE ZPVƊSF KVTU GFFEJOH UIF JOJUJBM TUBUF UP FBDI
DPNQVUBUJPO JO 4UBUF5 SBUIFS UIBO UISFBEJOH JU UISPVHI BT
ZPV HP 5IJT JT B HFOFSBM QBUUFSO DPOUSBTUJOH "QQMJDBUJWF
BOE .POBE BOE JT XPSUI DPOUFNQMBUJOH

*T JU QPTTJCMF UP JNQMFNFOU Ɖ "QQMJDBUJWF N
 "QQMJDB
UJWF 4UBUF5 T N
Ɖ http://stackoverflow.com/questions/18673525/
is-it-possible-to-implement-applicative-m-applicative-statet-s-m

https://github.com/NICTA/course/issues/134
$)"15&3  45"$, Ɖ&. 61 

 5IF .POBE JOTUBODF TIPVME MPPL GBJSMZ TJNJMBS UP UIF


.POBE JOTUBODF ZPV XSPUF GPS 3FBEFS5

instance (Monad m) => Monad (StateT s m) where


return = pure

sma >>= f = undefined

3FBEFS5 8SJUFS5 4UBUF5


8FƊE MJLF UP QPJOU TPNFUIJOH PVU BCPVU UIFTF UISFF UZQFT

newtype Reader r a =
Reader { runReader :: r -> a }

newtype Writer w a =
Writer { runWriter :: (a, w) }

newtype State s a =
State { runState :: s -> (a, s) }

BOE UIFJS USBOTGPSNFS WBSJBOUT


$)"15&3  45"$, Ɖ&. 61 

newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }

newtype WriterT w m a =
WriterT { runWriterT :: m (a, w) }

newtype StateT s m a =
StateT { runStateT :: s -> m (a, s) }

:PVƊSF BMSFBEZ GBNJMJBS XJUI 3FBEFS BOE 4UBUF 8F IBWFOƊU


TIPXO ZPV 8SJUFS PS 8SJUFS5 VQ UP UIJT QPJOU CFDBVTF RVJUF
GSBOLMZ ZPV TIPVMEOƊU VTF JU 8FƊMM FYQMBJO XIZ OPU JO B TFDUJPO
MBUFS JO UIJT DIBQUFS
'PS UIF QVSQPTFT PG UIF QSPHSFTTJPO XFƊSF USZJOH UP EFNPO
TUSBUF IFSF JU TVƸDFT UP LOPX UIBU UIF 8SJUFS "QQMJDBUJWF BOE
.POBE XPSL CZ DPNCJOJOH UIF Ԧ WBMVFT NPOPJEBMMZ 8JUI
UIBU JO NJOE XIBU XF DBO TFF JT UIBU 3FBEFS MFUT VT UBML BCPVU
WBMVFT XF OFFE 8SJUFS MFUT VT EFBM XJUI WBMVFT XF DBO FNJU
BOE DPNCJOF CVU OPU SFBE
BOE 4UBUF MFUT VT CPUI SFBE BOE
XSJUF WBMVFT JO BOZ NBOOFS XF EFTJSF ƈ JODMVEJOH NPOPJEBMMZ
MJLF 8SJUFS 5IJT JT POF SFBTPO ZPV OFFEOƊU CPUIFS XJUI 8SJUFS
TJODF 4UBUF DBO SFQMBDF JU BOZXBZ /PX ZPV LOPX XIZ ZPV
EPOƊU OFFE 8SJUFS XFƊMM UBML NPSF BCPVU XIZ ZPV EPOƊU XBOU
8SJUFS MBUFS
*O GBDU UIFSF JT B UZQF JO UIF transformers MJCSBSZ UIBU DPN
CJOFT 3FBEFS 8SJUFS BOE 4UBUF JOUP POF CJH UZQF
$)"15&3  45"$, Ɖ&. 61 

newtype RWST r w s m a =
RWST { runRWST :: r -> s -> m (a, s, w) }

#FDBVTF PG UIF 8SJUFS DPNQPOFOU ZPV QSPCBCMZ XPVMEOƊU


XBOU UP VTF UIBU JO NPTU BQQMJDBUJPOT FJUIFS CVU JUƊT HPPE UP
LOPX JU FYJTUT

$PSSFTQPOEFODF CFUXFFO 4UBUF5 BOE 1BSTFS


:PV NBZ SFDBMM XIBU B TJNQMF QBSTFS UZQF MPPLT MJLF

type Parser a = String -> Maybe (a, String)

:PV NBZ SFNFNCFS PVS EJTDVTTJPO BCPVU UIF TJNJMBSJUJFT


CFUXFFO QBSTFST BOE 4UBUF JO UIF 1BSTFST DIBQUFS /PX XF
DPVME DIPPTF UP EFƶOF B 1BSTFS UZQF JO UIF GPMMPXJOH NBOOFS

newtype StateT s m a =
StateT { runStateT :: s -> m (a,s) }

type Parser = StateT String Maybe

/PCPEZ EPFT UIJT JO QSBDUJDF CVU JUƊT VTFGVM UP DPOTJEFS UIF


TJNJMBSJUZ UP HFU B GFFM GPS XIBU 4UBUF5 JT BMM BCPVU
$)"15&3  45"$, Ɖ&. 61 

 5ZQFT ZPV QSPCBCMZ EPOƊU XBOU UP


VTF
/PU FWFSZ UZQF XJMM OFDFTTBSJMZ CF QFSGPSNBOU PS NBLF TFOTF
-JTU5 BOE 8SJUFS8SJUFS5 BSF FYBNQMFT PG UIJT

8IZ OPU VTF 8SJUFS PS 8SJUFS5


*UƊT B CJU UPP FBTZ UP HFU JOUP B TJUVBUJPO XIFSF 8SJUFS JT FJUIFS
UPP MB[Z PS UPP TUSJDU GPS UIF QSPCMFN ZPVƊSF TPMWJOH BOE UIFO
JUƊMM VTF NPSF NFNPSZ UIBO ZPVƊE MJLF 8SJUFS DBO BDDVNVMBUF
VOFWBMVBUFE UIVOLT DBVTJOH NFNPSZ MFBLT *UƊT BMTP JOBQQSP
QSJBUF GPS MPHHJOH MPOHSVOOJOH PS POHPJOH QSPHSBNT EVF UP
UIF GBDU UIBU ZPV DBOƊU SFUSJFWF BOZ PG UIF MPHHFE WBMVFT VOUJM
UIF DPNQVUBUJPO JT DPNQMFUF
6TVBMMZ XIFO 8SJUFS JT VTFE JO BO BQQMJDBUJPO JUƊT OPU DBMMFE
8SJUFS *OTUFBE B POFPƵ JT DSFBUFE GPS B TQFDJƶD UZQF Ԧ (JWFO
UIBU JUƊT TUJMM VTFGVM UP LOPX XIFO ZPVƊSF MPPLJOH BU TPNFUIJOH
UIBUƊT BDUVBMMZ B 3FBEFS 8SJUFS PS 4UBUF FWFO JG UIF BVUIPS
EJEOƊU VTF UIF UZQFT CZ UIPTF OBNFT GSPN UIF transformers
MJCSBSZ 4PNFUJNFT UIJT JT CFDBVTF UIFZ XBOUFE B TUSJDUFS 8SJUFS
UIBO UIF 4USJDU 8SJUFS BMSFBEZ BWBJMBCMF
%FUFSNJOJOH BOE NFBTVSJOH XIFO NPSF TUSJDUOFTT NPSF
FBHFSMZ FWBMVBUJOH ZPVS UIVOLT
JT OFFEFE JO ZPVS QSPHSBNT JT

*G ZPVƊE MJLF UP VOEFSTUBOE UIJT CFUUFS (BCSJFM (PO[BMF[ IBT B IFMQGVM CMPH QPTU PO
UIF TVCKFDU http://www.haskellforall.com/2014/02/streaming-logging.html
$)"15&3  45"$, Ɖ&. 61 

UIF UPQJD PG UIF VQDPNJOH DIBQUFS PO OPOTUSJDUOFTT

5IF -JTU5 ZPV XBOU JTOƊU NBEF GSPN UIF -JTU UZQF
5IF NPTU PCWJPVT XBZ UP JNQMFNFOU -JTU5 JT HFOFSBMMZ OPU
SFDPNNFOEFE GPS B WBSJFUZ PG SFBTPOT JODMVEJOH

 .PTU QFPQMFƊT ƶSTU BUUFNQU XPOƊU QBTT UIF BTTPDJBUJWJUZ MBX


8FƊSF OPU HPJOH UP TIPX ZPV B XBZ UP XSJUF JU UIBU EPFT
QBTT UIBU MBX CFDBVTF JUƊT OPU SFBMMZ XPSUI JU GPS UIF SFBTPOT
MJTUFE CFMPX

 *UƊT OPU WFSZ GBTU

 4USFBNJOH MJCSBSJFT MJLF pipes BOE conduit EP JU CFUUFS GPS


NPTU VTFDBTFT

1SJPS BSU GPS ƌ-JTU5 EPOF SJHIUƍ BMTP JODMVEFT "NC"NC5


CZ $POBM &MMJPUU BMUIPVHI ZPV XJMM QSPCBCMZ ƶOE JU DIBMMFOH
JOH UP VOEFSTUBOE JG ZPV BSFOƊU GBNJMJBS XJUI $POU5 BOE UIF
NPUJWBUJPO CFIJOE "NC
-JTUT JO )BTLFMM BSF BT NVDI B DPOUSPM TUSVDUVSF BT B EBUB
TUSVDUVSF TP TUSFBNJOH MJCSBSJFT TVDI BT pipes HFOFSBMMZ TVƸDF
JG ZPV OFFE B USBOTGPSNFS 5IJT JT MFTT PG B TUJDLJOH QPJOU JO
XSJUJOH BQQMJDBUJPOT UIBO ZPVƊE UIJOL

http://hackage.haskell.org/package/pipes

http://hackage.haskell.org/package/conduit

https://wiki.haskell.org/Amb
$)"15&3  45"$, Ɖ&. 61 

 3FDPWFSJOH BO PSEJOBSZ UZQF GSPN


B USBOTGPSNFS
*G ZPV IBWF B USBOTGPSNFS WBSJBOU PG B UZQF BOE XBOU UP VTF
JU BT JG JU XBT UIF OPOUSBOTGPSNFS WFSTJPO ZPV OFFE TPNF
Ԝ TUSVDUVSF UIBU EPFTOƊU SFBMMZ EP BOZUIJOH )BWF XF TFFO
BOZUIJOH MJLF UIBU 8IBU BCPVU Identity

Prelude> runMaybeT $ (+1) <$> MaybeT (Identity (Just 1))


Identity {runIdentity = Just 2}
Prelude> runMaybeT $ (+1) <$> MaybeT (Identity Nothing)
Identity {runIdentity = Nothing}

(JWFO UIBU XF DBO HFU *EFOUJUZ GSPN *EFOUJUZ5 BOE TP PO JO


UIF GPMMPXJOH NBOOFS

type MyIdentity a = IdentityT Identity a


type Maybe a = MaybeT Identity a
type Either e a = EitherT e Identity a
type Reader r a = ReaderT e Identity a
type State s a = StateT s Identity a

5IJT XPSLT ƶOF GPS SFDPWFSJOH UIF OPOUSBOTGPSNFS WBSJBOU


PG FBDI UZQF BT UIF *EFOUJUZ UZQF JT BDUJOH BT B CJU PG EPOPUIJOH
TUSVDUVSBM QBTUF GPS ƶMMJOH JO UIF HBQ
$)"15&3  45"$, Ɖ&. 61 

:FBI CVU XIZ :PV EPOƊU PSEJOBSJMZ OFFE UP EP UIJT JG ZPVƊSF


XPSLJOH XJUI B USBOTGPSNFS UIBU IBT B DPSSFTQPOEJOH OPO
USBOTGPSNFS UZQF ZPV DBO VTF 'PS FYBNQMF JUƊT MFTT DPNNPO
UP OFFE &YDFQU5 *EFOUJUZ
CFDBVTF UIF &JUIFS UZQF JT BMSFBEZ
UIFSF TP ZPV EPOƊU OFFE UP SFUSJFWF UIBU UZQF GSPN UIF USBOT
GPSNFS )PXFWFS JG ZPVƊSF XSJUJOH TPNFUIJOH XJUI TBZ 4DPUUZ
XIFSF B 3FBEFS5 JT QBSU PG UIF FOWJSPONFOU ZPV DBOƊU FBTJMZ
SFUSJFWF UIF 3FBEFS UZQF PVU PG UIBU CFDBVTF 3FBEFS JT OPU B
UZQF UIBU FYJTUT PO JUT PXO BOE ZPV DBOƊU NPEJGZ UIBU 3FBEFS5
XJUIPVU FTTFOUJBMMZ SFXSJUJOH BMM PG 4DPUUZ BOE XPX OPCPEZ
XBOUT UIBU GPS ZPV :PV NJHIU UIFO IBWF B TJUVBUJPO XIFSF XIBU
ZPVƊSF EPJOH POMZ OFFET B 3FBEFS OPU B 3FBEFS5 TP ZPV DPVME
VTF 3FBEFS5 *EFOUJUZ
UP CF DPNQBUJCMF XJUI 4DPUUZ XJUIPVU
IBWJOH UP SFXSJUF FWFSZUIJOH CVU TUJMM CFJOH BCMF UP LFFQ ZPVS
PXO DPEF B CJU UJHIUFS BOE TJNQMFS

5IF USBOTGPSNFST MJCSBSZ *O HFOFSBM EPOƊU VTF IBOESPMMFE


WFSTJPOT PG UIFTF USBOTGPSNFS UZQFT XJUIPVU HPPE SFBTPO :PV
DBO ƶOE NBOZ PG UIFN JO CBTF PS UIF transformers MJCSBSZ BOE
UIBU MJCSBSZ TIPVME IBWF DPNF XJUI ZPVS ()$ JOTUBMMBUJPO

" OPUF PO &YDFQU5 "MUIPVHI B MJCSBSZ DBMMFE either FYJTUT PO


)BDLBHF BOE QSPWJEFT UIF &JUIFS5 UZQF NPTU )BTLFMMFST BSF
NPWJOH UP UIF JEFOUJDBM ExceptT UZQF JO UIF transformers MJCSBSZ
"HBJO UIJT IBT NPTUMZ UP EP XJUI UIF GBDU UIBU transformers
$)"15&3  45"$, Ɖ&. 61 

DPNFT QBDLBHFE XJUI ()$ BMSFBEZ TP &YDFQU5 JT SFBEZUP


IBOE UIF VOEFSMZJOH UZQF JT UIF TBNF

 -FYJDBMMZ JOOFS JT TUSVDUVSBMMZ


PVUFS
0OF PG UIF USJDLJFS QBSUT PG NPOBE USBOTGPSNFST JT UIBU UIF
MFYJDBM SFQSFTFOUBUJPO PG UIF UZQFT XJMM WJPMBUF ZPVS JOUVJUJPOT
XJUI SFTQFDU UP UIF SFMBUJPOTIJQ JU IBT XJUI UIF TUSVDUVSF PG
ZPVS WBMVFT -FU VT OPUF TPNFUIJOH JO UIF EFƶOJUJPOT PG UIF
GPMMPXJOH UZQFT

-- definition in transformers may look


-- slightly different. It's not important.
newtype ExceptT e m a =
ExceptT { runExceptT :: m (Either e a)) }

newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a) }

newtype ReaderT r m a =
ReaderT { runReaderT :: r -> m a }

" OFDFTTBSZ CZQSPEVDU PG IPX USBOTGPSNFST XPSL JT UIBU


UIF BEEJUJPOBM TUSVDUVSF Ԝ JT BMXBZT XSBQQFE BSPVOE PVS WBMVF
0OF UIJOH UP OPUF JT UIBU JUƊT POMZ XSBQQFE BSPVOE UIJOHT
$)"15&3  45"$, Ɖ&. 61 

XF DBO IBWF OPU UIJOHT XF OFFE TVDI BT XJUI 3FBEFS5 5IF


DPOTFRVFODF PG UIJT JT UIBU B TFSJFT PG NPOBE USBOTGPSNFST JO B
UZQF XJMM CFHJO XJUI UIF JOOFSNPTU UZQF TUSVDUVSBMMZ TQFBLJOH
$POTJEFS UIF GPMMPXJOH

module OuterInner where

import Control.Monad.Trans.Except
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Reader

-- We only need to use return once


-- because it's one big Monad
embedded :: MaybeT (ExceptT String (ReaderT () IO)) Int
embedded = return 1

8F DBO TPSU PG QFFM BXBZ UIF MBZFST POF CZ POF


$)"15&3  45"$, Ɖ&. 61 

maybeUnwrap :: ExceptT String (ReaderT () IO) (Maybe Int)


maybeUnwrap = runMaybeT embedded

-- Next
eitherUnwrap :: ReaderT () IO (Either String (Maybe Int))
eitherUnwrap = runExceptT maybeUnwrap

-- Lastly
readerUnwrap :: () -> IO (Either String (Maybe Int))
readerUnwrap = runReaderT eitherUnwrap

5IFO JG XFƊE MJLF UP FWBMVBUF UIJT DPEF XF KVTU GFFE UIF VOJU
WBMVF UP UIF GVODUJPO

Prelude> readerUnwrap ()
Right (Just 1)

8IZ JT UIJT UIF SFTVMU $POTJEFS UIBU XF VTFE return GPS B


.POBE DPNQSJTFE PG 3FBEFS &JUIFS BOE .BZCF
$)"15&3  45"$, Ɖ&. 61 

instance Monad ((->) r) where


return = const

instance Monad (Either e) where


return = Right

instance Monad Maybe where


return = Just

8F DBO USFBU IBWJOH VTFE SFUVSO GPS UIF ƌPOFCJH.POBEƍ


PG 3FBEFS&JUIFS.BZCF BT DPNQPTJUJPO DPOTJEFS IPX XF HFU
UIF TBNF SFTVMU BT readerUnwrap () IFSF

Prelude> (const . Right . Just $ 1) ()


Right (Just 1)

" UFSNJOPMPHJDBM QPJOU UP LFFQ JO NJOE XIFO SFBEJOH BCPVU


NPOBE USBOTGPSNFST JT UIBU XIFO )BTLFMMFST TBZ ƌCBTF NPOBEƍ
UIFZ VTVBMMZ NFBO XIBU JT TUSVDUVSBMMZ PVUFSNPTU

type MyType a = IO [Maybe a]

*O MyType UIF CBTF NPOBE JT IO

&YFSDJTF 8SBQ *U 6Q
5VSO readerUnwrap GSPN UIF QSFWJPVT FYBNQMF CBDL JOUP embedded
UISPVHI UIF VTF PG UIF EBUB DPOTUSVDUPST GPS FBDI USBOTGPSNFS
$)"15&3  45"$, Ɖ&. 61 

-- Modify it to make it work.

embedded :: MaybeT (ExceptT String (ReaderT () IO)) Int


embedded = ??? (const (Right (Just 1)))

 .POBE5SBOT
8F PǒFO XBOU UP MJǒ GVODUJPOT JOUP B MBSHFS DPOUFYU 8FƊWF
CFFO EPJOH UIJT GPS B XIJMF XJUI Functor XIJDI MJǒT B GVODUJPO
JOUP B DPOUFYU PS BMUFSOBUJWFMZ MJǒT UIF GVODUJPO PWFS UIF
DPOUFYU
BOE BQQMJFT JU UP UIF WBMVF JOTJEF 5IF GBDJMJUZ UP
EP UIJT BMTP VOEFSHJSET "QQMJDBUJWF .POBE BOE 5SBWFSTBCMF
)PXFWFS fmap JTOƊU BMXBZT FOPVHI TP XF IBWF TPNF GVODUJPOT
UIBU BSF FTTFOUJBMMZ fmap GPS EJƵFSFOU DPOUFYUT

fmap :: Functor f => (a -> b) -> f a -> f b

liftA :: Applicative f => (a -> b) -> f a -> f b

liftM :: Monad m => (a -> r) -> m a -> m r

:PV NJHIU OPUJDF UIF MBUUFS UXP FYBNQMFT IBWF lift JO UIF
GVODUJPO OBNF 8IJMF XFƊWF FODPVSBHFE ZPV OPU UP HFU UPP
FYDJUFE BCPVU UIF NFBOJOH PG GVODUJPO OBNFT JO UIJT DBTF UIFZ
EP HJWF ZPV B DMVF PG XIBU UIFZƊSF EPJOH 5IFZ BSF MJǒJOH
KVTU BT fmap EPFT B GVODUJPO JOUP TPNF MBSHFS DPOUFYU 5IF
$)"15&3  45"$, Ɖ&. 61 

VOEFSMZJOH TUSVDUVSF PG UIF CJOE GVODUJPO GSPN .POBE JT BMTP


B MJǒJOH GVODUJPO ƈ fmap BHBJO ƈ DPNQPTFE XJUI UIF DSVDJBM
join GVODUJPO
*O TPNF DBTFT XF XBOU UP UBML BCPVU NPSF PS EJƵFSFOU
TUSVDUVSF UIBO UIFTF UZQFT QFSNJU *O PUIFS DBTFT XF XBOU
TPNFUIJOH UIBU EPFT BT NVDI MJǒJOH BT JT OFDFTTBSZ UP SFBDI
TPNF TUSVDUVSBMMZ
PVUFSNPTU QPTJUJPO JO B TUBDL PG NPOBE
USBOTGPSNFST .POBE USBOTGPSNFST DBO CF OFTUFE JO PSEFS
UP DPNQPTF WBSJPVT FƵFDUT JOUP POF NPOTUFS GVODUJPO CVU JO
PSEFS UP NBOBHF UIPTF TUBDLT ƶSTU XF OFFE UP MJǒ NPSF

5IF UZQFDMBTT UIBU MJǒT


.POBE5SBOT JT B UZQFDMBTT XJUI POF DPSF NFUIPE lift 4QFBL
JOH HFOFSBMMZ JU JT BCPVU MJǒJOH BDUJPOT JO TPNF .POBE PWFS
B USBOTGPSNFS UZQF XIJDI XSBQT JUTFMG JO UIF PSJHJOBM .POBE
'BODZ

class MonadTrans t where


-- | Lift a computation from the argument monad
-- to the constructed monad.
lift :: (Monad m) => m a -> t m a

)FSF UIF ԣ JT B DPOTUSVDUFE


NPOBE USBOTGPSNFS UZQF UIBU
IBT BO JOTUBODF PG .POBE5SBOT EFƶOFE
8FƊSF HPJOH UP XPSL UISPVHI B SFMBUJWFMZ VODPNQMJDBUFE
FYBNQMF GSPN 4DPUUZ OPX
$)"15&3  45"$, Ɖ&. 61 

.PUJWBUJOH .POBE5SBOT
:PV NBZ SFNFNCFS GSPN QSFWJPVT DIBQUFST UIBU 4DPUUZ JT B
XFC GSBNFXPSL GPS )BTLFMM 0OF UIJOH UP LOPX BCPVU 4DPUUZ
XJUIPVU HFUUJOH JOUP BMM UIF HSJUUZ EFUBJMT PG IPX JU XPSLT JT UIBU
UIF NPOBE USBOTGPSNFST UIF GSBNFXPSL SFMJFT PO BSF UIFN
TFMWFT OFXUZQFT GPS NPOBE USBOTGPSNFS TUBDLT 8BJU XIBU
8FMM MPPL

newtype ScottyT e m a =
ScottyT { runS :: State (ScottyState e m) a }
deriving ( Functor, Applicative, Monad )

newtype ActionT e m a =
ActionT { runAM :: ExceptT (ActionError e)
(ReaderT ActionEnv
(StateT ScottyResponse m)) a }
deriving ( Functor, Applicative )

type ScottyM = ScottyT Text IO


type ActionM = ActionT Text IO

8FƊMM VTF ActionM BOE ActionT BOE ScottyM BOE ScottyT BT JG


UIFZ XFSF UIF TBNF UIJOH CVU ZPV DBO TFF UIBU UIF . WBSJBOUT
BSF UZQF TZOPOZNT GPS UIF USBOTGPSNFST XJUI UIF JOOFS UZQFT
BMSFBEZ TFU 5IJT SPVHIMZ USBOTMBUFT UP UIF FSSPST UIF MFǒ TJEF PG
$)"15&3  45"$, Ɖ&. 61 

UIF ExceptT
JO ScottyM PS ActionM CFJOH SFUVSOFE BT Text XIJMF
UIF SJHIU TJEF PG UIF ExceptT XIBUFWFS JU EPFT JT IO ExceptT JT
UIF USBOTGPSNFS WFSTJPO PG Either BOE B ReaderT BOE B StateT
BSF TUBDLFE VQ JOTJEF UIBU BT XFMM 5IFTF JOUFSOBM NFDIBOJDT
EPOƊU NBUUFS UIBU NVDI UP ZPV BT B VTFS PG UIF 4DPUUZ "1* CVU
JUƊT VTFGVM UP TFF KVTU IPX NVDI JT QBDLFE VQ JO UIFSF
/PX CBDL UP PVS FYBNQMF 5IJT JT UIF ƌIFMMP XPSMEƍ FYBN
QMF VTJOH 4DPUUZ CVU UIF GPMMPXJOH XJMM DBVTF B UZQF FSSPS

-- scotty.hs

{-# LANGUAGE OverloadedStrings #-}

module Scotty where

import Web.Scotty

import Data.Monoid (mconcat)

main = scotty 3000 $ do


get "/:word" $ do
beam <- param "word"
putStrLn "hello"
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]

3FNJOEFS JO ZPVS UFSNJOBM ZPV DBO GPMMPX BMPOH XJUI UIJT


$)"15&3  45"$, Ɖ&. 61 

MJLF TP

$ stack build scotty


$ stack ghci
Prelude> :l scotty.hs

8IFO ZPV USZ UP MPBE JU ZPV TIPVME HFU B UZQF FSSPS

Couldn't match expected type


‘Web.Scotty.Internal.Types.ActionT
Data.Text.Internal.Lazy.Text IO a0’
with actual type ‘IO ()’

In a stmt of a 'do' block: putStrLn "hello"


In the second argument of ‘($)’, namely
‘do { beam <- param "word";
putStrLn "hello";
html $ mconcat ["<h1>Scotty, ", beam, ....] }’

5IF SFBTPO GPS UIJT UZQF FSSPS JT UIBU putStrLn IBT UIF UZQF
IO () CVU JU JT JOTJEF B do CMPDL JOTJEF PVS get BOE UIF NPOBE
UIBU DPEF JT JO JT UIFSFGPSF "DUJPO."DUJPO5

get :: RoutePattern -> ActionM () -> ScottyM ()

0VS "DUJPO5 UZQF FWFOUVBMMZ SFBDIFT IO CVU UIFSFƊT BEEJ


UJPOBM TUSVDUVSF XF OFFE UP MJǒ PWFS ƶSTU 5P ƶY UIJT XFƊMM TUBSU
CZ BEEJOH BO JNQPSU
$)"15&3  45"$, Ɖ&. 61 

import Control.Monad.Trans.Class

"OE BNFOE UIBU MJOF XJUI putStrLn UP UIF GPMMPXJOH

lift (putStrLn "hello")

*U TIPVME XPSL
:PV DBO BTTFSU B UZQF GPS UIF lift FNCFEEFE JO UIF 4DPUUZ
BDUJPO

(lift :: IO a -> ActionM a) (putStrLn "hello")

-FUƊT TFF XIBU JU EPFT -PBE UIF ƶMF BHBJO BOE DBMM UIF main
GVODUJPO :PV TIPVME TFF UIJT NFTTBHF

Setting phasers to stun... (port 3000) (ctrl-c to quit)

*O UIF BEESFTT CBS PG ZPVS XFC CSPXTFS UZQF localhost:3000


:PV TIPVME OPUJDF UXP UIJOHT POF JT UIBU UIFSF JT OPUIJOH JO
UIF beam TMPU PG UIF UFYU UIBU QSJOUT UP ZPVS TDSFFO BOE UIF PUIFS
JT UIBU JU QSJOUT ƌIFMMPƍ UP ZPVS UFSNJOBM XIFSF UIF QSPHSBN JT
SVOOJOH 5SZ BEEJOH B XPSE UP UIF FOE PG UIF BEESFTT

localhost:3000/beam

5IF UFYU PO ZPVS TDSFFO TIPVME DIBOHF BOE IFMMP TIPVME


QSJOU JO ZPVS UFSNJOBM BHBJO 5IBU ƌXPSEƍ QBSBNFUFS JT XIBU
IBT CFFO CPVOE WJB UIF WBSJBCMF beam JOUP UIBU IUNM MJOF BU UIF
$)"15&3  45"$, Ɖ&. 61 

FOE PG UIF do CMPDL XIJMF UIF ƌIFMMPƍ IBT CFFO MJǒFE PWFS UIF
"DUJPO. TP UIBU JU DBO QSJOU JO ZPVS UFSNJOBM *U XJMM QSJOU BO
PUIFS ƌIFMMPƍ UP ZPVS UFSNJOBM FWFSZ UJNF TPNFUIJOH IBQQFOT
PO UIF XFC QBHF
8F DBO DPODSFUJ[F PVS VTF PG lift JO UIF GPMMPXJOH TUFQT
1MFBTF GPMMPX BMPOH CZ BTTFSUJOH UIF UZQFT GPS UIF BQQMJDBUJPO
PG lift JO UIF 4DPUUZ BQQMJDBUJPO BCPWF

lift :: (Monad m, MonadTrans t) => m a -> t m a


lift :: (MonadTrans t) => IO a -> t IO a
lift :: IO a -> ActionM a
lift :: IO () -> ActionM ()

8F HP GSPN (t IO a) UP (ActionM a) CFDBVTF UIF *0 JT JOTJEF


UIF "DUJPO.
-FUƊT FYBNJOF ActionM NPSF DBSFGVMMZ

Prelude> import Web.Scotty


Prelude> import Web.Scotty.Trans
Prelude> :info ActionM
type ActionM = ActionT Data.Text.Internal.Lazy.Text IO
-- Defined in ‘Web.Scotty’

8F DBO TFF GPS PVSTFMWFT XIBU UIJT lift EJE CZ MPPLJOH BU


UIF .POBE5SBOT JOTUBODF GPS "DUJPO5 XIJDI JT XIBU "DUJPO.
JT B UZQF BMJBT PG
$)"15&3  45"$, Ɖ&. 61 

instance MonadTrans (ActionT e) where


lift = ActionT . lift . lift . lift

1BSU PG UIF OJDFOFTT IFSF JT UIBU ActionT JT JUTFMG EFƶOFE JO


UFSNT PG UISFF NPSF NPOBE USBOTGPSNFST 8F DBO TFF UIJT JO
UIF EFƶOJUJPO PG ActionT

newtype ActionT e m a =
ActionT {
runAM :: ExceptT (ActionError e)
(ReaderT ActionEnv
(StateT ScottyResponse m)) a }
deriving (Functor, Applicative)

-FUƊT ƶSTU SFQMBDF UIF lift GPS "DUJPO5 XJUI JUT EFƶOJUJPO BOE
TFF JG JU TUJMM XPSLT
$)"15&3  45"$, Ɖ&. 61 

{-# LANGUAGE OverloadedStrings #-}

module Scotty where

import Web.Scotty
import Web.Scotty.Internal.Types (ActionT(..))
import Control.Monad.Trans.Class
import Data.Monoid (mconcat)

main = scotty 3000 $ do


get "/:word" $ do
beam <- param "word"
(ActionT . lift . lift . lift) (putStrLn "hello")
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]

5IJT TIPVME TUJMM XPSL /PUF UIBU XF IBE UP BTL GPS UIF EBUB
DPOTUSVDUPS GPS ActionT GSPN BO *OUFSOBM NPEVMF CFDBVTF UIF
JNQMFNFOUBUJPO JT IJEEFO CZ EFGBVMU 8FƊWF HPU UISFF MJǒT
POF FBDI GPS &YDFQU5 3FBEFS5 BOE 4UBUF5
/FYU XFƊMM EP &YDFQU5

instance MonadTrans (ExceptT e) where


lift = ExceptT . liftM Right

5P VTF UIBU JO PVS DPEF BEE UIF GPMMPXJOH JNQPSU

import Control.Monad.Trans.Except
$)"15&3  45"$, Ɖ&. 61 

"OE PVS BQQ DIBOHFT JOUP UIF GPMMPXJOH

main = scotty 3000 $ do


get "/:word" $ do
beam <- param "word"
(ActionT
. (ExceptT . liftM Right)
. lift
. lift) (putStrLn "hello")
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]

5IFO GPS 3FBEFS5 XF UBLF B HBOEFS BU $POUSPM.POBE5SBOT3FBE


JO UIF transformers MJCSBSZ BOE TFF UIF GPMMPXJOH

instance MonadTrans (ReaderT r) where


lift = liftReaderT

liftReaderT :: m a -> ReaderT r m a


liftReaderT m = ReaderT (const m)

'PS SFBTPOT
MJǒ3FBEFS5 JTOƊU FYQPSUFE CZ transformers
CVU XF DBO SFEFƶOF JU PVSTFMWFT "EE UIF GPMMPXJOH UP UIF
NPEVMF
$)"15&3  45"$, Ɖ&. 61 

import Control.Monad.Trans.Reader

liftReaderT :: m a -> ReaderT r m a


liftReaderT m = ReaderT (const m)

5IFO PVS BQQ DBO CF EFƶOFE BT GPMMPXT

main = scotty 3000 $ do


get "/:word" $ do
beam <- param "word"
(ActionT
. (ExceptT . fmap Right)
. liftReaderT
. lift
) (putStrLn "hello")
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]

0S JOTUFBE PG MJǒ3FBEFS5 XF DPVMEƊWF EPOF

. (\m -> ReaderT (const m))

0S

(ActionT
. (ExceptT . fmap Right)
. ReaderT . const
. lift
) (putStrLn "hello")
$)"15&3  45"$, Ɖ&. 61 

/PX GPS UIBU MBTU lift PWFS 4UBUF5 3FNFNCFSJOH UIBU JU XBT
UIF MB[Z 4UBUF5 UIBU UIF UZQF PG "DUJPO5 NFOUJPOFE XF TFF UIF
GPMMPXJOH .POBE5SBOT JOTUBODF

instance MonadTrans (StateT s) where


lift m = StateT $ \ s -> do
a <- m
return (a, s)

'JSTU MFUƊT HFU PVS JNQPSU JO QMBDF

import Control.Monad.Trans.State.Lazy hiding (get)

8F OFFEFE UP IJEF get CFDBVTF 4DPUUZ BMSFBEZ IBT B EJƵFSFOU


get GVODUJPO EFƶOFE BOE XF EPOƊU OFFE UIF POF GSPN 4UBUF5
5IFO JOMJOJOH UIBU JOUP PVS BQQ DPEF
$)"15&3  45"$, Ɖ&. 61 

main = scotty 3000 $ do


get "/:word" $ do
beam <- param "word"
(ActionT
. (ExceptT . fmap Right)
. ReaderT . const
. \m -> StateT (\s -> do
a <- m
return (a, s))
) (putStrLn "hello")
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]

/PUF UIBU XF OFFEFE BO PVUFS MBNCEB CFGPSF UIF 4UBUF5 JO


PSEFS UP HFU UIF NPOBEJD BDUJPO XF XFSF MJǒJOH "U UIJT QPJOU
XFƊSF JO UIF PVUFSNPTU QPTJUJPO XF DBO CF BOE TJODF "DUJPO.
EFƶOFT "DUJPO5ƊT PVUFSNPTU NPOBEJD UZQF BT CFJOH *0 UIBU
NFBOT PVS putStrLn XPSLT ƶOF BǒFS BMM UIJT MJǒJOH
5ZQJDBMMZ B .POBE5SBOT JOTUBODF MJǒT PWFS POMZ POF MBZFS
BU B UJNF CVU 4DPUUZ BCTUSBDUT BXBZ UIF VOEFSMZJOH TUSVDUVSF
TP UIBU ZPV EPOƊU IBWF UP DBSF 5IBUƊT XIZ JU HPFT BIFBE BOE
EPFT UIF OFYU UISFF MJǒT GPS ZPV 5IF DSJUJDBM UIJOH UP SFBMJ[F
IFSF JT UIBU MJǒJOH NFBOT ZPVƊSF FNCFEEJOH BO FYQSFTTJPO JO
B MBSHFS DPOUFYU CZ BEEJOH TUSVDUVSF UIBU EPFTOƊU EP BOZUIJOH
$)"15&3  45"$, Ɖ&. 61 

.POBE5SBOT JOTUBODFT
/PX ZPV TFF XIZ XF IBWF .POBE5SBOT BOE IBWF B QJDUVSF PG
XIBU lift UIF POMZ NFUIPE PG .POBE5SBOT EPFT
)FSF BSF TPNF FYBNQMFT PG .POBE5SBOT JOTUBODFT

 *EFOUJUZ5

instance MonadTrans IdentityT where


lift = IdentityT

 .BZCF5

instance MonadTrans MaybeT where


lift = MaybeT . liftM Just

lift :: (Monad m) => m a -> t m a


(MaybeT . liftM Just) :: Monad m => m a -> MaybeT m a

MaybeT :: m (Maybe a) -> MaybeT m a


(liftM Just) :: Monad m => m a -> m (Maybe a)

3PVHIMZ TQFBLJOH UIJT IBT UBLFO BO m a BOE MJǒFE JU JOUP


B .BZCF5 DPOUFYU
5IF HFOFSBM QBUUFSO XJUI .POBE5SBOT JOTUBODFT EFNPO
TUSBUFE CZ .BZCF5 JT UIBU ZPVƊSF VTVBMMZ HPJOH UP MJǒ UIF
JOKFDUJPO PG UIF LOPXO TUSVDUVSF XJUI .BZCF5 UIF LOPXO
$)"15&3  45"$, Ɖ&. 61 

TUSVDUVSF JT .BZCF
PWFS TPNF .POBE *OKFDUJPO PG TUSVD
UVSF VTVBMMZ NFBOT return CVU TJODF XJUI .BZCF5 XF LOPX
XF XBOU .BZCF TUSVDUVSF XF DIPPTF UP OPU CF PCGVTDBUPSZ
BOE VTF +VTU 5IBU USBOTGPSNT BO m a JOUP m (T a) XIFSF
DBQJUBM 5 JT TPNF DPODSFUF UZQF ZPVƊSF MJǒJOH UIF m a JOUP
5IFO UP DBQ JU BMM PƵ ZPV VTF UIF EBUB DPOTUSVDUPS GPS ZPVS
NPOBE USBOTGPSNFS BOE UIF WBMVF JT OPX MJǒFE JOUP UIF
MBSHFS DPOUFYU )FSFƊT B TVNNBSZ PG UIF TUBHFT UIF UZQF
PG UIF WBMVF HPFT UISPVHI

v :: Monad m => m a
liftM Just :: Monad m => m a -> m (Maybe a)
liftM Just v :: m (Maybe a)
MaybeT (liftM Just v) :: MaybeT m a

4FF JG ZPV DBO XPSL PVU UIF UZQFT PG UIJT POF

 3FBEFS5

instance MonadTrans (ReaderT r) where


lift = ReaderT . const

"OE OPX XSJUF TPNF JOTUBODFT

&YFSDJTFT -Jǒ .PSF

,FFQ JO NJOE XIBU UIFTF BSF EPJOH GPMMPX UIF UZQFT MJǒ UJMM
ZPV ESPQ
$)"15&3  45"$, Ɖ&. 61 

 :PV UIPVHIU ZPV XFSF EPOF XJUI &JUIFS5

instance MonadTrans (EitherT e) where


lift = undefined

 0S 4UBUF5 5IJT POFƊMM CF NPSF PCOPYJPVT *UƊT ƶOF JG ZPVƊWF


TFFO UIJT CFGPSF

instance MonadTrans (StateT s) where


lift = undefined

1SPMJƶD MJǒJOH JT UIF GBJMVSF NPEF


"QPMPHJFT UP UIF PSJHJOBM BVUIPST CVU TPNFUJNFT XJUI UIF VTF
PG DPODSFUFMZ BOE FYQMJDJUMZ UZQFE NPOBE USBOTGPSNFST ZPVƊMM
TFF TUVƵ MJLF UIJT
$)"15&3  45"$, Ɖ&. 61 

addSubWidget :: (YesodSubRoute sub master) =>


sub
-> GWidget sub master a
-> GWidget sub' master a
addSubWidget sub w =
do master <- liftHandler getYesod
let sr = fromSubRoute sub master
i <- GWidget $ lift $ lift $ lift $ lift
$ lift $ lift $ lift get
w' <- liftHandler
$ toMasterHandlerMaybe sr (const sub) Nothing
$ flip runStateT i $ runWriterT $ runWriterT
$ runWriterT $ runWriterT $ runWriterT
$ runWriterT $ runWriterT $ unGWidget w
let ((((((((a,
body),
title),
scripts),
stylesheets),
style),
jscript),
h),
i') = w'
GWidget $ do
tell body
lift $ tell title
lift $ lift $ tell scripts
$)"15&3  45"$, Ɖ&. 61 

%P OPU XSJUF DPEF MJLF UIJT &TQFDJBMMZ EP OPU XSJUF DPEF


MJLF UIJT BOE UIFO QSPDFFE UP CMPH BCPVU IPX UFSSJCMF NPOBE
USBOTGPSNFST BSF

8SBQ JU TNBDL JU QSFMJǒ JU


0, TP IPX EP XF BWPJE UIBU IPSSPS TIPX 8FMM UIFSF BSF
BDUVBMMZ B MPU PG XBZT CVU POF PG UIF NPTU SPCVTU BOE DPN
NPO JT OFXUZQJOH ZPVS .POBE TUBDL BOE BCTUSBDUJOH BXBZ
UIF SFQSFTFOUBUJPO 'SPN UIFSF ZPV QSPWJEF UIF GVODUJPOBM
JUZ MFWFSBHJOH UIF SFQSFTFOUBUJPO BT QBSU PG ZPVS "1* " HPPE
FYBNQMF PG UIJT DPNFT UP VT GSPNƒ4DPUUZ
-FUƊT UBLF B HBOEFS BU UIF ActionM UZQF XF NFOUJPOFE FBSMJFS

Prelude> import Web.Scotty


-- again, to make the type read more nicely
-- we import some other modules.
Prelude> import Data.Text.Lazy
Prelude> :info ActionM
type ActionM = Web.Scotty.Internal.Types.ActionT Text IO
-- Defined in ‘Web.Scotty’

)VN 4DPUUZ IJEFT UIF VOEFSMZJOH UZQF CZ EFGBVMU CFDBVTF


ZPV PSEJOBSJMZ XPVMEOƊU DBSF PS UIJOL BCPVU JU JO UIF DPVSTF
PG XSJUJOH ZPVS BQQMJDBUJPO 8IBU 4DPUUZ EPFT IFSF JT HPPE
QSBDUJDF 4DPUUZƊT EFTJHO LFFQT UIF VOEFSMZJOH JNQMFNFOUBUJPO
$)"15&3  45"$, Ɖ&. 61 

IJEEFO CZ EFGBVMU CVU MFUT VT JNQPSU BO *OUFSOBM NPEVMF UP HFU


BU UIF SFQSFTFOUBUJPO JO DBTF XF OFFE UP

Prelude> import Web.Scotty.Internal.Types


-- more modules to clean up the types
Prelude> import Control.Monad.Trans.Reader
Prelude> import Control.Monad.Trans.State.Lazy
Prelude> import Control.Monad.Trans.Except

Prelude> :info ActionT


type role ActionT nominal representational nominal
newtype ActionT e (m :: * -> *) a
= ActionT
{runAM :: ExceptT
(ActionError e)
(ReaderT ActionEnv
(StateT ScottyResponse m))
a}
instance (Monad m, ScottyError e) => Monad (ActionT e m)
instance Functor m => Functor (ActionT e m)
instance Monad m => Applicative (ActionT e m)

8IBUƊT OJDF BCPVU UIJT BQQSPBDI JT UIBU JU TVCKFDUT UIF DPO


TVNFST XIJDI DPVME JODMVEF ZPVSTFMG
PG ZPVS UZQF UP MFTT
OPJTF XJUIJO BO BQQMJDBUJPO *U BMTP EPFTOƊU SFRVJSF SFBEJOH
QBQFST XSJUUFO CZ QFPQMF USZJOH WFSZ IBSE UP JNQSFTT B UIFTJT
$)"15&3  45"$, Ɖ&. 61 

BEWJTPS BMUIPVHI QPLJOH UISPVHI QSJPS BSU GPS JEFBT JT SFD


PNNFOEFE *U DBO SFEVDF PS FMJNJOBUF NBOVBM MJǒJOH XJUIJO
UIF .POBE BT XFMM /PUF UIBU XF POMZ IBE UP VTF lift PODF
UP QFSGPSN BO *0 BDUJPO JO ActionM FWFO UIPVHI UIF VOEFSMZ
JOH JNQMFNFOUBUJPO IBT NPSF UIBO POF USBOTGPSNFS ƷZJOH
BSPVOE

 .POBE*0 BLB [PPN[PPN


5IFSFƊT NPSF UIBO POF XBZ UP TLJO B DBU BOE UIFSFƊT NPSF UIBO
POF XBZ UP MJǒ BO BDUJPO PWFS BEEJUJPOBM TUSVDUVSF .POBE*0
JT B EJƵFSFOU EFTJHO UIBO MonadTrans CFDBVTF SBUIFS UIBO MJǒJOH
UISPVHI POF ƌMBZFSƍ BU B UJNF .POBE*0 JT JOUFOEFE UP LFFQ
MJǒJOH ZPVS *0 BDUJPO VOUJM JU JT MJǒFE PWFS BMM TUSVDUVSF FN
CFEEFE JO UIF PVUFSNPTU *0 UZQF 5IF JEFB IFSF JT UIBU ZPVƊE
XSJUF liftIO PODF BOE JU XPVME JOTUBOUJBUF UP BMM PG UIF GPMMPXJOH
UZQFT KVTU ƶOF

liftIO :: IO a -> ExceptT e IO a


liftIO :: IO a -> ReaderT r IO a
liftIO :: IO a -> StateT s IO a
-- As Sir Mix-A-Lot once said, stack 'em up deep
liftIO :: IO a -> StateT s (ReaderT r IO) a
liftIO :: IO a -> ExceptT e (StateT s (ReaderT r IO)) a

:PV EPOƊU IBWF UP MJǒ NVMUJQMF UJNFT JG ZPVƊSF USZJOH UP SFBDI


$)"15&3  45"$, Ɖ&. 61 

B CBTF PVUFSNPTU
NPOBE UIBU IBQQFOT UP CF *0 CFDBVTF ZPV
IBWF liftIO
*O UIF transformers MJCSBSZ UIF .POBE*0 DMBTT SFTJEFT JO UIF
NPEVMF $POUSPM.POBE*0$MBTT

class (Monad m) => MonadIO m where


-- | Lift a computation from the 'IO' monad.
liftIO :: IO a -> m a

5IF DPNNFOUBSZ XJUIJO UIF NPEVMF JT SFBTPOBCMZ IFMQGVM


UIPVHI JU EPFTOƊU IJHIMJHIU XIBU NBLFT .POBE*0 EJƵFSFOU
GSPN .POBE5SBOT

.POBET JO XIJDI *0 DPNQVUBUJPOT NBZ CF FNCFE


EFE "OZ NPOBE CVJMU CZ BQQMZJOH B TFRVFODF PG
NPOBE USBOTGPSNFST UP UIF *0 NPOBE XJMM CF BO JO
TUBODF PG UIJT DMBTT
*OTUBODFT TIPVME TBUJTGZ UIF GPMMPXJOH MBXT XIJDI
TUBUF UIBU MJǒ*0 JT B USBOTGPSNFS PG NPOBET

 liftIO . return = return

 liftIO (m >>= f) = liftIO m >>= (liftIO . f)

-FU VT NPEJGZ UIF 4DPUUZ FYBNQMF BQQ UP QSJOU B TUSJOH


$)"15&3  45"$, Ɖ&. 61 

{-# LANGUAGE OverloadedStrings #-}

module Main where

import Web.Scotty

import Control.Monad.IO.Class
import Data.Monoid (mconcat)

main = scotty 3000 $ do


get "/:word" $ do
beam <- param "word"
liftIO (putStrLn "hello")
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]

*G ZPV UIFO SVO UIF main GVODUJPO JO B 3&1- PS CVJME B CJOBSZ


BOE FYFDVUF JU ZPVƊMM CF BCMF UP SFRVFTU B SFTQPOTF GSPN UIF
TFSWFS VTJOH ZPVS XFC CSPXTFS BT XF TIPXFE ZPV FBSMJFS
PS
B DPNNBOEMJOF BQQMJDBUJPO MJLF DVSM *G ZPV VTFE B CSPXTFS
BOE TFF ƌIFMMPƍ QSJOUFE NPSF UIBO PODF JUƊT IJHIMZ MJLFMZ ZPVS
CSPXTFS NBEF UIF SFRVFTU NPSF UIBO PODF :PV TIPVMEOƊU TFF
UIJT CFIBWJPS JG ZPV UFTU JU XJUI DVSM

&YBNQMF .POBE*0 JOTUBODFT


 *EFOUJUZ5
$)"15&3  45"$, Ɖ&. 61 

instance (MonadIO m) => MonadIO (IdentityT m) where


liftIO = IdentityT . liftIO

 &JUIFS5

instance (MonadIO m) => MonadIO (EitherT e m) where


liftIO = lift . liftIO

&YFSDJTFT 4PNF *OTUBODFT


 .BZCF5

instance (MonadIO m) => MonadIO (MaybeT m) where


liftIO = undefined

 3FBEFS5

instance (MonadIO m) => MonadIO (ReaderT r m) where


liftIO = undefined

 4UBUF5

instance (MonadIO m) => MonadIO (StateT s m) where


liftIO = undefined

)JOU ZPVS JOTUBODFT TIPVME CF TJNQMF


$)"15&3  45"$, Ɖ&. 61 

 .POBE USBOTGPSNFST JO VTF


.BZCF5 JO VTF
5IFTF BSF KVTU TPNF FYBNQMF PG .BZCF5 JO VTF XF XJMM OPU
DPNNFOU VQPO UIFN BOE JOTUFBE MFU ZPV SFTFBSDI UIFN GVS
UIFS ZPVSTFMG JG ZPV XBOU 0SJHJOT PG UIF DPEF BSF OPUFE JO UIF
TBNQMFT

-- github.com/wavewave/hoodle-core
recentFolderHook :: MainCoroutine (Maybe FilePath)
recentFolderHook = do
xstate <- get
(r :: Maybe FilePath) <- runMaybeT $ do
hset <- hoist (view hookSet xstate)
rfolder <- hoist (H.recentFolderHook hset)
liftIO rfolder
return r

-- github.com/devalot/hs-exceptions src/maybe.hs
addT :: FilePath -> FilePath -> IO (Maybe Integer)
addT f1 f2 = runMaybeT $ do
s1 <- sizeT f1
s2 <- sizeT f2
return (s1 + s2)
$)"15&3  45"$, Ɖ&. 61 

-- wavewave/ghcjs-dom-delegator example/Example.hs
main :: IO ()
main = do
clickbarref <- asyncCallback1 AlwaysRetain clickbar
clickbazref <- asyncCallback1 AlwaysRetain clickbaz
r <- runMaybeT $ do
doc <- MaybeT currentDocument
bar <- lift . toJSRef
=<< MaybeT (documentQuerySelector doc
(".bar" :: JSString))
baz <- lift . toJSRef
=<< MaybeT (documentQuerySelector doc
(".baz" :: JSString))
lift $ do
ref <- newObj
del <-delegator ref
addEvent bar "click" clickbarref
addEvent baz "click" clickbazref

case r of
Nothing -> print "something wrong"
Just _ -> print "welldone"
$)"15&3  45"$, Ɖ&. 61 

5FNQPSBSZ FYUFOTJPO PG TUSVDUVSF


"MUIPVHI XF DPNNPOMZ UIJOL PG NPOBE USBOTGPSNFST BT CFJOH
VTFE UP EFƶOF POF CJH DPOUFYU GPS BO BQQMJDBUJPO QBSUJDVMBSMZ
XJUI UIJOHT MJLF 3FBEFS5 UIFSF BSF PUIFS XBZT 0OF QBUUFSO
UIBU JT PǒFO VTFGVM JT UFNQPSBSJMZ FYUFOEJOH BEEJUJPOBM TUSVD
UVSF UP BWPJE CPJMFSQMBUF )FSFƊT BO FYBNQMF VTJOH QMBJO PME
.BZCF BOE 4DPUUZ
$)"15&3  45"$, Ɖ&. 61 

{-# LANGUAGE OverloadedStrings #-}

module Main where

import Control.Monad.IO.Class
import Data.Maybe (fromMaybe)
import Data.Text.Lazy (Text)
import Web.Scotty

param' :: Parsable a => Text -> ActionM (Maybe a)


param' k = rescue (Just <$> param k)
(const (return Nothing))

main = scotty 3000 $ do


get "/:word" $ do
beam' <- param' "word"
let beam = fromMaybe "" beam'
i <- param' "num"
liftIO $ print (i :: Maybe Integer)
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]

5IJT XPSLT XFMM FOPVHI CVU DPVME HFU UFEJPVT JO B IVSSZ JG


XF IBE B CVODI PG TUVƵ UIBU SFUVSOFE ActionM (Maybe ...) BOE
XF XBOUFE UP TIPSUDJSDVJU UIF NPNFOU BOZ PG UIFN GBJMFE 4P
XF EP TPNFUIJOH TJNJMBS CVU XJUI .BZCF5 BOE CVJMEJOH VQ
$)"15&3  45"$, Ɖ&. 61 

NPSF EBUB JO POF HP


$)"15&3  45"$, Ɖ&. 61 

{-# LANGUAGE OverloadedStrings #-}

module Main where

import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe
import Data.Maybe (fromMaybe)
import Data.Text.Lazy (Text)
import Web.Scotty

param' :: Parsable a => Text -> MaybeT ActionM a


param' k = MaybeT $
rescue (Just <$> param k)
(const (return Nothing))

type Reco = (Integer, Integer, Integer, Integer)

main = scotty 3000 $ do


get "/:word" $ do
beam <- param "word"
reco <- runMaybeT $ do
a <- param' "1"
liftIO $ print a
b <- param' "2"
c <- param' "3"
d <- param' "4"
$)"15&3  45"$, Ɖ&. 61 

4PNF JNQPSUBOU UIJOHT UP OPUF IFSF

 8F POMZ IBE UP VTF liftIO PODF FWFO JO UIF QSFTFODF PG


BEEJUJPOBM TUSVDUVSF XIFSFBT XJUI lift XF IBE UP MJǒ UXJDF
UP BEESFTT .BZCF5 BOE "DUJPO.

 5IF ƌPOF CJH CJOEƍ PG UIF MaybeT NFBOT XF DPVME UBLF


UIF FYJTUFODF PG Ԑ ԑ Ԓ BOE ԓ GPS HSBOUFE JO UIBU DPOUFYU
CVU UIF reco WBMVF JUTFMG JT Maybe Reco CFDBVTF BOZ QBSU PG
UIF DPNQVUBUJPO DPVME GBJM JO UIF BCTFODF PG UIF OFFEFE
QBSBNFUFS

 *U LOPXT XIBU NPOBE XF NFBO GPS UIBU doCMPDL CFDBVTF


PG UIF runMaybeT JO GSPOU PG UIF do 5IJT TFSWFT UIF EVBM
QVSQPTF PG VOQBDLJOH UIF .BZCF5 JOUP BO ActionM (Maybe
Reco) XIJDI XF DBO CJOE PVU JOUP Maybe Reco

&YDFQU5 BLB &JUIFS5 JO VTF


5IF FYBNQMF XJUI .BZCF BOE 4DPUUZ NBZ OPU IBWF UPUBMMZ
TBUJTƶFE CFDBVTF UIF GBJMVSF NPEF JTOƊU SFBMMZ IFMQGVM UP BO
FOEVTFS ƈ BMM UIFZ LOPX JT ƌ/PUIJOHƍ "DDPSEJOHMZ .BZCF JT
VTVBMMZ TPNFUIJOH UIBU TIPVME HFU IBOEMFE FBSMZ BOE PǒFO JO B
QMBDF MPDBM UP XIFSF JU XBT QSPEVDFE TP UIBU ZPV BWPJE NZTUFSJ
PVT /PUIJOH WBMVFT ƷPBUJOH BSPVOE BOE TIPSUDJSDVJUJOH ZPVS
DPEF 5IFZƊSF OPU TPNFUIJOH ZPV SFBMMZ XBOU UP SFUVSO UP FOE
VTFST FJUIFS 'PSUVOBUFMZ XF IBWF Either GPS NPSF EFTDSJQUJWF
TIPSUDJSDVJUJOH DPNQVUBUJPOT
$)"15&3  45"$, Ɖ&. 61 

4DPUUZ BHBJO

8FƊMM VTF 4DPUUZ BHBJO UP EFNPOTUSBUF UIJT 0ODF BHBJO XFƊMM


TIPX ZPV B QMBJO FYBNQMF
$)"15&3  45"$, Ɖ&. 61 

{-# LANGUAGE OverloadedStrings #-}

module Main where

import Control.Monad.IO.Class
import Data.Text.Lazy (Text)
import Web.Scotty

param' :: Parsable a => Text -> ActionM (Either String a)


param' k = rescue (Right <$> param k)
(const
(return
(Left $ "The key: "
++ show k
++ " was missing!")))

main = scotty 3000 $ do


get "/:word" $ do
beam <- param "word"
a <- param' "1"
let a' = either (const 0) id a
liftIO $ print (a :: Either String Int)
liftIO $ print (a' :: Int)
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]
$)"15&3  45"$, Ɖ&. 61 

/PUF UIBU XF IBE UP NBOVBMMZ GPME UIF &JUIFS JG XF XBOUFE


UP BEESFTT UIF EFTJSFE *OU WBMVF 5SZ UP BWPJE IBWJOH EFGBVMU
GBMMCBDL WBMVFT JO SFBM DPEF UIPVHI 5IJT DPVME HFU OVUUZ JO
B IVSSZ JG XF IBE NBOZ UIJOHT XF XFSF QVMMJOH PVU PG UIF
QBSBNFUFST
-FUƊT EP UIBU CVU XJUI &YDFQU5 GSPN transformers 3FNFN
CFS &YDFQU5 JT KVTU BOPUIFS OBNF GPS &JUIFS5
$)"15&3  45"$, Ɖ&. 61 

{-# LANGUAGE OverloadedStrings #-}

module Main where

import Control.Monad.IO.Class
import Control.Monad.Trans.Class
import Control.Monad.Trans.Except
import Data.Text.Lazy (Text)
import qualified Data.Text.Lazy as TL
import Web.Scotty

param' :: Parsable a => Text -> ExceptT String ActionM a


param' k = ExceptT $
rescue (Right <$> param k)
(const
(return
(Left $ "The key: "
++ show k
++ " was missing!")))

type Reco = (Integer, Integer, Integer, Integer)

tshow = TL.pack . show

main = scotty 3000 $ do


get "/" $ do
reco <- runExceptT $ do
$)"15&3  45"$, Ɖ&. 61 

*G ZPV QBTT JU B SFRVFTU MJLF

http://localhost:3000/?1=1

*UƊMM BTL GPS UIF QBSBNFUFS 2 CFDBVTF UIBU XBT UIF OFYU QBSBN
ZPV BTLFE GPS BǒFS 1
*G ZPV QBTT JU B SFRVFTU MJLF

http://localhost:3000/?1=1&2=2&3=3&4=4

:PV TIPVME TFF UIF SFTQPOTF JO ZPVS CSPXTFS PS UFSNJOBM


PG

Success! Reco was: (1,2,3,4)

"T CFGPSF XF HFU UP CFOFƶU GSPN POF CJH CJOE VOEFS UIF
&YDFQU5

4MJHIUMZ NPSF BEWBODFE DPEF

'SPN TPNF DPEF CZ 4FBO $IBMNFST 


4PNF DPOUFYU GPS UIF EitherT BQQMJDBUJPO ZPVƊMM TFF

https://github.com/mankyKitty/Meteor/

http://mankykitty.github.io/
$)"15&3  45"$, Ɖ&. 61 

type Et a = EitherT SDLErr IO a

mkWindow :: HasSDLErr m =>


String
-> CInt -> CInt
-> m SDL.Window
mkRenderer :: HasSDLErr m => SDL.Window -> m SDL.Renderer

hasSDLErr :: (MonadIO m, MonadError e m) =>


(a -> b)
-> (a -> Bool)
-> e -> IO a -> m b
hasSDLErr g f e a =
liftIO a
>>= \r -> bool (return $ g r) (throwError e) $ f r

class (MonadIO m, MonadError SDLErr m) => HasSDLErr m where


decide :: (a -> Bool) -> SDLErr -> IO a -> m a
decide' :: (Eq n, Num n) => SDLErr -> IO n -> m ()

instance HasSDLErr (EitherT SDLErr IO) where


decide = hasSDLErr id
decide' = hasSDLErr (const ()) (/= 0)

5IFO JO VTF
$)"15&3  45"$, Ɖ&. 61 

initialise :: Et (SDL.Window,SDL.Renderer)
initialise = do
initSDL [SDL.SDL_INIT_VIDEO]
win <- mkWindow "Meteor!" screenHeight screenWidth
rdr <- mkRenderer win
return (win,rdr)

createMeteor :: IO (Either SDLErr MeteorS)


createMeteor = do
eM <- runEitherT initialise
return $ mkMeteor <$> eM
where
emptyBullets = V.empty

mkMeteor (w,r) = MeteorS w r


getInitialPlayer
emptyBullets -- no missiles at start
getInitialMobs
False

 .POBET EP OPU DPNNVUF


3FNFNCFS UIBU NPOBET JO HFOFSBM EP OPU DPNNVUF BOE
ZPV BSFOƊU HVBSBOUFFE TPNFUIJOH TFOTJCMF GPS FWFSZ QPTTJCMF
DPNCJOBUJPO PG UZQFT 5IF LJU XF IBWF GPS DPOTUSVDUJOH BOE
$)"15&3  45"$, Ɖ&. 61 

VTJOH NPOBE USBOTGPSNFST JT VTFGVM CVU JT OPU B MJDFOTF UP OPU


UIJOL

)ZQPUIFUJDBM &YFSDJTF
$POTJEFS ReaderT r Maybe BOE MaybeT (Reader r) ƈ BSF UIFTF
UZQFT FRVJWBMFOU %P UIFZ EP UIF TBNF UIJOH 5SZ XSJUJOH
PUIFSXJTF TJNJMBS CJUT PG DPEF XJUI FBDI BOE TFF JG ZPV DBO
QSPWF UIFZƊSF UIF TBNF PS EJƵFSFOU

 5SBOTGPSN JG ZPV XBOU UP


*G ZPV ƶOE NPOBE USBOTGPSNFST EJƸDVMU PS BOOPZJOH UIFO
EPOƊU CPUIFS .PTU PG UIF UJNF ZPV DBO HFU CZ XJUI liftIO BOE
QMBJO *0 BDUJPOT GVODUJPOT .BZCF WBMVFT FUD %P UIF TJN
QMFTU GPS ZPV
UIJOH ƶSTU XIFO NBQQJOH PVU TPNFUIJOH OFX PS
VOGBNJMJBS *UƊT CFUUFS UP MFU NPSF TUSVDUVSFE GPSNVMBUJPOT PG
QSPHSBNT GBMM PVU OBUVSBMMZ GSPN IBWJOH LJDLFE BSPVOE TPNF
UIJOH VODPNQMJDBUFE UIBO UP CMPX PVU ZPVS XPSLJOH NFNPSZ
CVEHFU JO POF HP %POƊU XPSSZ BCPVU TFFNJOH VOTPQIJTUJDBUFE
JO PVS PQJOJPO CFJOH IBQQZ BOE QSPEVDUJWF JT CFUUFS UIBO
CFJOH GBODZ
,FFQ JU CBTJD JO ZPVS ƶSTU BUUFNQU /FWFS NBLF JU NPSF
FMBCPSBUF JOJUJBMMZ UIBO JT TUSJDUMZ OFDFTTBSZ :PVƊMM ƶHVSF PVU
XIFO UIF USBOTGPSNFS WBSJBOU PG B UZQF XJMM TBWF ZPV DPNQMFY
JUZ JO UIF QSPDFTT PG XSJUJOH ZPVS QSPHSBNT 8F IBWF UBLFO
$)"15&3  45"$, Ɖ&. 61 

ZPV UISPVHI UIFTF UPQJDT CFDBVTF ZPVƊMM OFFE BU MFBTU B QBTT


JOH GBNJMJBSJUZ OPU UP HFU TUVDL JO NPEFSO )BTLFMM MJCSBSJFT PS
GSBNFXPSLT CVU JUƊT OPU B EFTJHO EJDUBUF ZPV NVTU GPMMPX
*O B MBUFS DIBQUFS XFƊMM CF TIPXJOH ZPV TPNFUIJOH UIBU ZPV
NJHIU ƶOE NPSF BQQFBMJOH PS OJDFS UIBO DPODSFUF NPOBE
USBOTGPSNFST CVU ZPV TUJMM TIPVMEOƊU DPOTJEFS UIBU BO JOWJUBUJPO
UP QSFNBUVSF FMBCPSBUJPO

 $IBQUFS &YFSDJTFT


8SJUF UIF DPEF
 rDec JT B GVODUJPO UIBU TIPVME HFU JUT BSHVNFOU JO UIF DPO
UFYU PG 3FBEFS BOE SFUVSO B WBMVF EFDSFNFOUFE CZ POF

rDec :: Num a => Reader a a


rDec = undefined

Prelude> import Control.Monad.Trans.Reader


Prelude> runReader rDec 1
0
Prelude> fmap (runReader rDec) [1..10]
[0,1,2,3,4,5,6,7,8,9]

/PUF UIBU ƌ3FBEFSƍ GSPN transformers JT BDUVBMMZ 3FBEFS5


PG *EFOUJUZ BOE UIBU runReader JT B DPOWFOJFODF GVODUJPO
$)"15&3  45"$, Ɖ&. 61 

UISPXJOH BXBZ UIF NFBOJOHMFTT TUSVDUVSF GPS ZPV 1MBZ


XJUI runReaderT JG JU UJDLMFT ZPVS OPOEFTDSJQU GVSSZ SFE
QVQQFU

 0ODF ZPV IBWF BO rDec UIBU XPSLT NBLF JU BOE BOZ JOOFS
MBNCEBT QPJOUGSFF JG UIBUƊT OPU BMSFBEZ UIF DBTF

 rShow JT show CVU JO 3FBEFS

rShow :: Show a => ReaderT a Identity String


rShow = undefined

Prelude> runReader rShow 1


"1"
Prelude> fmap (runReader rShow) [1..10]
["1","2","3","4","5","6","7","8","9","10"]

 0ODF ZPV IBWF BO rShow UIBU XPSLT NBLF JU QPJOUGSFF

 rPrintAndInc XJMM ƶSTU QSJOU UIF JOQVU XJUI B HSFFUJOH UIFO


SFUVSO UIF JOQVU JODSFNFOUFE CZ POF

rPrintAndInc :: (Num a, Show a) => ReaderT a IO a


rPrintAndInc = undefined

Prelude> runReaderT rPrintAndInc 1


Hi: 1
2
$)"15&3  45"$, Ɖ&. 61 

Prelude> traverse (runReaderT rPrintAndInc) [1..10]


Hi: 1
Hi: 2
Hi: 3
Hi: 4
Hi: 5
Hi: 6
Hi: 7
Hi: 8
Hi: 9
Hi: 10
[2,3,4,5,6,7,8,9,10,11]

 sPrintIncAccum ƶSTU QSJOUT UIF JOQVU XJUI B HSFFUJOH UIFO


QVUT UIF JODSFNFOUFE JOQVU BT UIF OFX TUBUF BOE SFUVSOT
UIF PSJHJOBM JOQVU BT B 4USJOH

sPrintIncAccum :: (Num a, Show a) => StateT a IO String


sPrintIncAccum = undefined

Prelude> runStateT sPrintIncAccum 10


Hi: 10
("10",11)
Prelude> mapM (runStateT sPrintIncAccum) [1..5]
Hi: 1
Hi: 2
$)"15&3  45"$, Ɖ&. 61 

Hi: 3
Hi: 4
Hi: 5
[("1",2),("2",3),("3",4),("4",5),("5",6)]

'JY UIF DPEF


5IF DPEF XPOƊU UZQFDIFDL BT XSJUUFO ƶY JU TP UIBU JU EPFT 'FFM
GSFF UP BEE JNQPSUT JG JU QSPWJEFT TPNFUIJOH VTFGVM 'VODUJPOT
XJMM CF VTFE UIBU XF IBWFOƊU JOUSPEVDFE :PVƊSF OPU BMMPXFE
UP DIBOHF UIF UZQFT BTTFSUFE :PV NBZ IBWF UP ƶY UIF DPEF JO
NPSF UIBO POF QMBDF
$)"15&3  45"$, Ɖ&. 61 

import Control.Monad.Trans.Maybe
import Control.Monad

isValid :: String -> Bool


isValid v = '!' `elem` v

maybeExcite :: MaybeT IO String


maybeExcite = do
v <- getLine
guard $ isValid v
return v

doExcite :: IO ()
doExcite = do
putStrLn "say something excite!"
excite <- maybeExcite
case excite of
Nothing -> putStrLn "MOAR EXCITE"
Just e -> putStrLn ("Good, was very excite: " ++ e)

)JU DPVOUFS
8FƊSF HPJOH UP QSPWJEF BO JOJUJBM TDBƵPME PG B 4DPUUZ BQQMJDBUJPO
XIJDI DPVOUT IJUT UP TQFDJƶD 63*T *U BMTP QSFƶYFT UIF LFZT
XJUI B QSFƶY EFƶOFE PO BQQ JOJUJBMJ[BUJPO SFUSJFWFE WJB UIF
$)"15&3  45"$, Ɖ&. 61 

DPNNBOEMJOF BSHVNFOUT

{-# LANGUAGE OverloadedStrings #-}

module Main where

import Control.Monad.Trans.Class
import Control.Monad.Trans.Reader
import Data.IORef
import qualified Data.Map as M
import Data.Maybe (fromMaybe)
import Data.Text.Lazy (Text)
import qualified Data.Text.Lazy as TL
import System.Environment (getArgs)
import Web.Scotty.Trans

data Config =
Config {
-- that's one, one click!
-- two...two clicks!
-- Three BEAUTIFUL clicks! ah ah ahhhh
counts :: IORef (M.Map Text Integer)
, prefix :: Text
}
$)"15&3  45"$, Ɖ&. 61 

-- Stuff inside ScottyT is, except for things that escape


-- via IO, effectively read-only so we can't use StateT.
-- It would overcomplicate things to attempt to do so and
-- you should be using a proper database for production
-- applications.
type Scotty = ScottyT Text (ReaderT Config IO)
type Handler = ActionT Text (ReaderT Config IO)

bumpBoomp :: Text
-> M.Map Text Integer
-> (M.Map Text Integer, Integer)
bumpBoomp k m = undefined

app :: Scotty ()
app =
get "/:key" $ do
unprefixed <- param "key"
let key' = mappend undefined unprefixed
newInteger <- undefined
html $ mconcat [ "<h1>Success! Count was: "
, TL.pack $ show newInteger
, "</h1>"
]
$)"15&3  45"$, Ɖ&. 61 

main :: IO ()
main = do
[prefixArg] <- getArgs
counter <- newIORef M.empty
let config = undefined
runR = undefined
scottyT 3000 runR app

$PEF JT NJTTJOH BOE CSPLFO :PVS UBTL JT UP NBLF JU XPSL


XIBUFWFS JT OFDFTTBSZ
:PV TIPVME CF BCMF UP SVO UIF TFSWFS GSPN JOTJEF PG ()$J
QBTTJOH BSHVNFOUT MJLF TP

Prelude> :main lol


Setting phasers to stun... (port 3000) (ctrl-c to quit)

:PV DPVME BMTP CVJME B CJOBSZ BOE QBTT UIF BSHVNFOUT GSPN
ZPVS TIFMM CVU EP XIBU ZPV MJLF 0ODF JUƊT SVOOJOH ZPV TIPVME
CF BCMF UP CVNQ UIF DPVOUT MJLF TP

$ curl localhost:3000/woot
<h1>Success! Count was: 1</h1>
$ curl localhost:3000/woot
<h1>Success! Count was: 2</h1>
$ curl localhost:3000/blah
<h1>Success! Count was: 1</h1>
$)"15&3  45"$, Ɖ&. 61 

/PUF UIBU UIF VOEFSMZJOH ƌLFZƍ VTFE JO UIF DPVOUFS XIFO


ZPV GET /woot JT "lolwoot" CFDBVTF XF QBTTFE ƍMPMƍ UP main 'PS
B HJHHMF USZ UIF 63* GPS POF PG UIF LFZT JO ZPVS CSPXTFS BOE
NBTI SFGSFTI B CVODI

.PSSB
 8SJUF UIF HBNF .PSSB VTJOH 4UBUF5 BOE *0 5IF TUBUF
CFJOH BDDVNVMBUFE JT UIF TDPSF PG UIF QMBZFS BOE UIF DPN
QVUFS "* UIF QMBZFS JT QMBZJOH BHBJOTU 5P TUBSU NBLF UIF
DPNQVUFS DIPPTF JUT QMBZ SBOEPNMZ
0O FYJU SFQPSU UIF TDPSFT GPS UIF QMBZFS BOE UIF DPNQVUFS
DPOHSBUVMBUJOH UIF XJOOFS

 "EE B IVNBO WT IVNBO NPEF UP UIF HBNF XJUI JOUFS


TUJUJBM TDSFFOT CFUXFFO JOQVU QSPNQUT TP UIF QMBZFST DBO
DIBOHF PVU PG UIF IPUTFBU XJUIPVU TFFJOH UIF PUIFS QMBZFSƊT
BOTXFS

 *NQSPWF UIF DPNQVUFS "* TMJHIUMZ CZ NBLJOH JU SFNFN


CFS HSBNT PG UIF QMBZFSƊT CFIBWJPS BEKVTUJOH JUT BOTXFS
JOTUFBE PG EFDJEJOH SBOEPNMZ XIFO UIF QMBZFSƊT CFIBWJPS
NBUDIFT B LOPXO CFIBWJPS 'PS FYBNQMF

-- p is Player
-- c is Computer

https://en.wikipedia.org/wiki/Morra_(game)
$)"15&3  45"$, Ɖ&. 61 

-- Player is odds, computer is evens.


P: 1
C: 1
- C wins
P: 2
C: 1
- P wins
P: 2
C: 1
- P wins

"U UIJT QPJOU UIF DPNQVUFS TIPVME SFHJTUFS UIF QBUUFSO 


 
QMBZFS QJDLFE  BǒFS  BOE  /FYU UJNF UIF QMBZFS
QJDLT  GPMMPXFE CZ  UIF DPNQVUFS TIPVME BTTVNF UIF
OFYU QMBZ XJMM CF  BOE QJDL  JO PSEFS UP XJO

 5IF HSBN UIJOH JT QSFUUZ TJNQMF BOE EVNC )VNBOT BSF


TUJMM CBE BU CFJOH SBOEPN UIFZ PǒFO IBWF TVCQBUUFSOT
JO UIFJS NPWFT

 'PMMPXVQ SFTPVSDFT


 1BSBMMFM BOE $PODVSSFOU 1SPHSBNNJOH JO )BTLFMM 4JNPO
.BSMPX http://chimera.labs.oreilly.com/books/1230000000929
$IBQUFS 

/POTUSJDUOFTT

1SPHSFTT EPFTOƊU DPNF


GSPN FBSMZ SJTFST ƈ
QSPHSFTT JT NBEF CZ MB[Z
NFO MPPLJOH GPS FBTJFS
XBZT UP EP UIJOHT

3PCFSU " )FJOMFJO


$)"15&3  /0/453*$5/&44 

 -B[JOFTT
5IJT DIBQUFS DPODFSOT UIF XBZT JO XIJDI )BTLFMM QSPHSBNT
BSF FWBMVBUFE 8FƊWF BEESFTTFE UIJT B CJU JO QSFWJPVT DIBQUFST
GPS FYBNQMF JO UIF 'PMET DIBQUFS XIFSF XF XFOU JOUP TPNF
EFUBJM BCPVU IPX GPMET FWBMVBUF *O UIJT DIBQUFS PVS HPBM JT UP
HJWF ZPV FOPVHI JOGPSNBUJPO BCPVU )BTLFMMƊT MB[Z FWBMVBUJPO
TUSBUFHZ UIBU ZPVƊMM CF BCMF UP SFBTPO DPOƶEFOUMZ BCPVU UIF
SFEVDUJPO QSPDFTT PG ZPVS FYQSFTTJPOT BOE JOUSPEVDF TUSJDUFS
FWBMVBUJPO XIFSF UIBU JT XBOUFE
.PTU QSPHSBNNJOH MBOHVBHFT IBWF TUSJDU FWBMVBUJPO TFNBO
UJDT )BTLFMM UFDIOJDBMMZ IBT ƌOPOTUSJDUƍ ƈ OPU MB[Z ƈ FWBM
VBUJPO CVU UIF EJƵFSFODF CFUXFFO MB[Z BOE OPOTUSJDU JT OPU
QSBDUJDBMMZ SFMFWBOU TP ZPVƊMM IFBS )BTLFMM SFGFSSFE UP BT FJUIFS
B MB[Z MBOHVBHF PS B OPOTUSJDU POF
" WFSZ SPVHI PVUMJOF PG )BTLFMMƊT FWBMVBUJPO TUSBUFHZ JT UIJT
NPTU FYQSFTTJPOT BSF POMZ SFEVDFE PS FWBMVBUFE XIFO OFDFT
TBSZ 8IFO UIF FWBMVBUJPO QSPDFTT CFHJOT B UIVOL JT DSFBUFE
GPS FBDI FYQSFTTJPO 8FƊMM HP JOUP NPSF EFUBJM BCPVU UIJT JO
UIF DIBQUFS CVU B UIVOL JT MJLF B QMBDFIPMEFS JO UIF VOEFSMZ
JOH HSBQI PG UIF QSPHSBN 8IBUFWFS FYQSFTTJPO UIF UIVOL JT
IPMEJOH B QMBDF GPS DBO CF FWBMVBUFE XIFO OFDFTTBSZ CVU JG
JUƊT OFWFS OFFEFE JU OFWFS HFUT SFEVDFE BOE UIFO UIF HBSCBHF
DPMMFDUPS DPNFT BMPOH BOE TXFFQT JU BXBZ *G JU JT FWBMVBUFE
CFDBVTF JUƊT JO B HSBQI JU DBO CF PǒFO TIBSFE CFUXFFO FYQSFT
TJPOT ƈ UIBU JT PODF x = 1 + 1 IBT CFFO FWBMVBUFE BOZUJNF ԧ
$)"15&3  /0/453*$5/&44 

JT GPSDFE JU EPFT OPU IBWF UP CF SFDPNQVUFE


5IJT JT UIF MB[JOFTT PG )BTLFMM EPOƊU EP NPSF XPSL UIBO
OFFEFE %POƊU FWBMVBUF VOUJM OFDFTTBSZ %POƊU SFFWBMVBUF JG
ZPV EPOƊU IBWF UP 8FƊMM HP UISPVHI UIF EFUBJMT PG IPX UIJT
XPSLT FYDFQUJPOT UP UIF HFOFSBM QSJODJQMFT BOE IPX UP DPOUSPM
UIF FWBMVBUJPO CZ BEEJOH TUSJDUOFTT XIFSF EFTJSFE
4QFDJƶDBMMZ XF XJMM

Ƒ EFƶOF DBMMCZOBNF BOE DBMMCZOFFE FWBMVBUJPO

Ƒ FYQMBJO UIF NBJO FƵFDUT PG OPOTUSJDU FWBMVBUJPO

Ƒ MJWF UIF 5IVOL -JGF 

Ƒ DPOTJEFS UIF SVOUJNF CFIBWJPS PG OPOTUSJDU DPEF JO UFSNT


PG TIBSJOH

Ƒ EFWFMPQ NFUIPET GPS PCTFSWJOH TIBSJOH BOE NFBTVSJOH


QSPHSBN FƸDJFODZ

Ƒ CPUUPN PVU XJUI UIF CPUUPNT

 0CTFSWBUJPOBM #PUUPN 5IFPSZ


*O PVS EJTDVTTJPO BCPVU OPOTUSJDUOFTT JO )BTLFMM XFƊSF HP
JOH UP CF UBMLJOH BCPVU CPUUPN B MPU 5IJT JT QBSUMZ CFDBVTF
OPOTUSJDUOFTT JT EFƶOFE CZ UIF BCJMJUZ UP FWBMVBUF FYQSFTTJPOT

8F MPWF ZPV +FTTF

0CTFSWBUJPOBM CPUUPN UIFPSZ JT OPU B SFBM UIJOH %P OPU FNBJM VT BCPVU UIJT
$)"15&3  /0/453*$5/&44 

UIBU IBWF CJOEJOHT XIJDI BSF CPUUPN JO UIFN BT MPOH BT UIF


CPUUPN JUTFMG JT OFWFS GPSDFE #PUUPNT BMTP HJWF VT B DPOWF
OJFOU NFUIPE PG PCTFSWJOH FWBMVBUJPO JO )BTLFMM #Z DBVTJOH
UIF QSPHSBN UP IBMU JNNFEJBUFMZ XJUI BO FSSPS CPUUPN TFSWFT
BT PVS ƶSTU NFBOT PG VOEFSTUBOEJOH OPOTUSJDUOFTT JO )BTLFMM
:PV QSPCBCMZ SFDBMM XF IBWF VTFE UIJT USJDL CFGPSF

4UBOEBSET BOE PCMJHBUJPOT


5FDIOJDBMMZ )BTLFMM JT POMZ PCMJHBUFE UP CF OPOTUSJDU OPU MB[Z
" USVMZ MB[Z MBOHVBHF NFNPJ[FT PS IPMET JO NFNPSZ UIF
SFTVMUT PG BMM UIF GVODUJPOT JU EPFT FWBMVBUF BOE PVUTJEF PG UPZ
QSPHSBNT UIJT UFOET UP VTF VOBDDFQUBCMZ MBSHF BNPVOUT PG
NFNPSZ *NQMFNFOUBUJPOT PG )BTLFMM TVDI BT ()$ )BTLFMM
BSF POMZ PCMJHBUFE UP CF OPOTUSJDU TVDI UIBU UIFZ IBWF UIF
TBNF CFIBWJPS XJUI SFTQFDU UP CPUUPN UIFZ BSF OPU SFRVJSFE
UP UBLF B QBSUJDVMBS BQQSPBDI UP IPX UIF QSPHSBN FYFDVUFT PS
IPX FƸDJFOUMZ JU EPFT TP
5IF FTTFODF PG OPOTUSJDUOFTT JT UIBU ZPV DBO IBWF BO FY
QSFTTJPO XIJDI SFTVMUT JO B WBMVF FWFO JG CPUUPN PS JOƶOJUF
EBUB MVSLT XJUIJO 'PS FYBNQMF UIF GPMMPXJOH XPVME POMZ XPSL
JO B OPOTUSJDU MBOHVBHF

Prelude> fst (1, undefined)


1
Prelude> snd (undefined, 2)
2
$)"15&3  /0/453*$5/&44 

5IF JEFB JT UIBU BOZ HJWFO JNQMFNFOUBUJPO PG OPOTUSJDUOFTT


JT BDDFQUBCMF BT MPOH BT JU SFTQFDUT XIFO JUƊT TVQQPTFE UP SFUVSO
B WBMVF TVDDFTTGVMMZ PS CPUUPN PVU

 0VUTJEF JO JOTJEF PVU


4USJDU MBOHVBHFT FWBMVBUF JOTJEF PVU OPOTUSJDU MBOHVBHFT MJLF
)BTLFMM FWBMVBUF PVUTJEF JO 0VUTJEF JO NFBOT UIBU FWBMVBUJPO
QSPDFFET GSPN UIF PVUFSNPTU QBSUT PG FYQSFTTJPOT BOE XPSLT
JOXBSE CBTFE PO XIBU WBMVFT BSF GPSDFE 5IJT NFBOT UIF PSEFS
PG FWBMVBUJPO BOE XIBU HFUT FWBMVBUFE DBO WBSZ EFQFOEJOH PO
JOQVUT
5IF GPMMPXJOH FYBNQMF JT XSJUUFO JO B TMJHIUMZ BSDBOF XBZ
UP NBLF UIF FWBMVBUJPO PSEFS NPSF PCWJPVT

possiblyKaboom =
\f -> f fst snd (0, undefined)

-- booleans in lambda form


true :: a -> a -> a
true = \a -> (\b -> a)

false :: a -> a -> a


false = \a -> (\b -> b)

8IFO XF BQQMZ possiblyKaboom UP true true JT UIF ԕ fst JT


UIF Ԑ BOE snd JT UIF ԑ 4FNBOUJDBMMZ DBTF NBUDIFT HVBSET
$)"15&3  /0/453*$5/&44 

FYQSFTTJPOT BOE JGUIFOFMTF FYQSFTTJPOT DPVME BMM CF SFXSJUUFO


JO UIJT NBOOFS UIFZ BSF OPU JO GBDU EFDPNQPTFE UIJT XBZ CZ UIF
DPNQJMFS
CZ OFTUJOH MBNCEBT BOE SFEVDJOH GSPN UIF PVUTJEF
JO

(\f -> f fst snd (0, undefined)) (\a -> (\b -> a))
(\a -> (\b -> a)) fst snd (0, undefined)
(\b -> fst) snd (0, undefined)
fst (0, undefined)
0

5IF OFYU FYBNQMF JT XSJUUFO JO NPSF OPSNBM )BTLFMM CVU


XJMM SFUVSO UIF TBNF SFTVMU 8IFO XF BQQMZ UIF GVODUJPO UP
5SVF IFSF XF DBTF PO UIF 5SVF UP SFUVSO UIF ƶSTU WBMVF PG UIF
UVQMF

possiblyKaboom b =
case b of
True -> fst tup
False -> snd tup
where tup = (0, undefined)

5IF CPUUPN JT JOTJEF B UVQMF BOE UIF UVQMF JT CPVOE JOTJEF


PG B MBNCEB UIBU DBTFT PO B CPPMFBO WBMVF BOE SFUVSOT FJUIFS UIF
ƶSTU PS TFDPOE FMFNFOU PG UIF UVQMF 4JODF XF TUBSU FWBMVBUJOH
GSPN UIF PVUTJEF BT MPOH BT UIJT GVODUJPO JT POMZ FWFS BQQMJFE
UP 5SVF UIBU CPUUPN XJMM OFWFS DBVTF B QSPCMFN )PXFWFS BU
$)"15&3  /0/453*$5/&44 

UIF SJTL PG TUBUJOH UIF PCWJPVT XF EP OPU FODPVSBHF ZPV UP


XSJUF QSPHSBNT XJUI CPUUPNT MZJOH BSPVOE XJMMZOJMMZ
8IFO XF TBZ FWBMVBUJPO XPSLT PVUTJEF JO XFƊSF UBMLJOH
BCPVU FWBMVBUJOH B TFSJFT PG OFTUFE FYQSFTTJPOT BOE OPU POMZ
BSF XF TUBSUJOH GSPN UIF PVUTJEF BOE XPSLJOH JO CVU XFƊSF BMTP
POMZ FWBMVBUJOH TPNF PG UIF FYQSFTTJPOT TPNF PG UIF UJNF *O
)BTLFMM XF FWBMVBUF FYQSFTTJPOT XIFO XF OFFE UIFN SBUIFS
UIBO XIFO UIFZ BSF ƶSTU SFGFSSFE UP PS DPOTUSVDUFE 5IJT JT POF
PG UIF XBZT JO XIJDI OPOTUSJDUOFTT NBLFT )BTLFMM FYQSFTTJWF
ƈ XF DBO SFGFS UP WBMVFT CFGPSF XFƊWF EPOF UIF XPSL UP DSFBUF
UIFN
5IJT QBUUFSO BQQMJFT UP EBUB TUSVDUVSFT BOE MBNCEBT BMJLF
:PVƊWF BMSFBEZ TFFO UIF FƵFDUT PG PVUTJEFJO FWBMVBUJPO JO UIF
DIBQUFS PO GPMET 0VUTJEFJO FWBMVBUJPO JT XIZ XF DBO UBLF UIF
MFOHUI PG B MJTU XJUIPVU UPVDIJOH BOZ PG UIF DPOUFOUT $POTJEFS
UIF GPMMPXJOH

-- using a dated definition for foldr


foldr k z xs = go xs
where
go [] = z
go (y:ys) = y `k` go ys

c = foldr const 'z' ['a'..'e']

&YQBOEJOH UIF foldr JO Ԓ


$)"15&3  /0/453*$5/&44 

c = const 'z' "abcde" = go "abcde"


where
go [] = 'z'
go ('a':"bcde") = 'a' `const` go "bcde"

-- So the first step of evaluating


-- of the fold here is:

const 'a' (go "bcde")

const x y = x
const 'a' (go "bcde") = 'a'

5IF TFDPOE BSHVNFOU BOE TUFQ PG UIF GPME JT OFWFS FWBMV


BUFE

const 'a' _ = 'a'

*U EPFTOƊU FWFO NBUUFS JG UIF OFYU WBMVF JT CPUUPN

Prelude> foldr const 'z' ['a', undefined]


'a'

5IJT JT PVUTJEFJO TIPXJOH JUTFMG 5IF const GVODUJPO XBT JO


UIF PVUFSNPTU QPTJUJPO TP JU XBT FWBMVBUFE ƶSTU
$)"15&3  /0/453*$5/&44 

 8IBU EPFT UIF PUIFS XBZ MPPL MJLF


*O TUSJDU MBOHVBHFT ZPV DBOOPU PSEJOBSJMZ CJOE B DPNQVUBUJPO UP
B OBNF XJUIPVU IBWJOH BMSFBEZ EPOF BMM UIF XPSL UP DPOTUSVDU
JU
8FƊMM VTF UIJT FYBNQMF QSPHSBN UP DPNQBSF JOTJEFPVU BOE
PVUTJEFJO TUSJDU BOE OPOTUSJDU
FWBMVBUJPO TUSBUFHJFT

module OutsideIn where

hypo :: IO ()
hypo = do
let x :: Int
x = undefined
s <- getLine
case s of
"hi" -> print x
_ -> putStrLn "hello"

'PS B TUSJDU MBOHVBHF UIJT JT B QSPCMFN " TUSJDU MBOHVBHF


DBOOPU FWBMVBUF hypo TVDDFTTGVMMZ VOMFTT UIF ԧ JTOƊU CPUUPN
5IJT JT CFDBVTF TUSJDU MBOHVBHFT XJMM GPSDF UIF CPUUPN CFGPSF
CJOEJOH ԧ " TUSJDU MBOHVBHF JT FWBMVBUJOH FBDI CJOEJOH BT JU
DPNFT JOUP TDPQF OPU XIFO B CJOEJOH JT VTFE
*O OPOTUSJDU )BTLFMM ZPV DBO QSPCBCMZ HVFTT IPX UIJTƊMM HP

Prelude> hypo
$)"15&3  /0/453*$5/&44 

s
hello
Prelude> hypo
hi
*** Exception: Prelude.undefined

5IF JEFB JT UIBU FWBMVBUJPO JT ESJWFO CZ EFNBOE OPU CZ


DPOTUSVDUJPO 8F EPOƊU HFU UIF FYDFQUJPO VOMFTT XFƊSF GPSDJOH
FWBMVBUJPO PG ԧ ƈ PVUTJEF JO

$BO XF NBLF )BTLFMM TUSJDU


-FUƊT TFF JG XF DBO SFQMJDBUF UIF SFTVMUT PG B TUSJDU MBOHVBHF
UIPVHI XIJDI XJMM HJWF VT B HPPE QJDUVSF PG IPX )BTLFMM JT
EJƵFSFOU 8F DBO BEE TUSJDUOFTT IFSF JO UIF GPMMPXJOH NBOOFS

hypo' :: IO ()
hypo' = do
let x :: Integer
x = undefined
s <- getLine
case x `seq` s of
"hi" -> print x
_ -> putStrLn "hello"

3VOOJOH JU XJMM HJWF UIJT SFTVMU


$)"15&3  /0/453*$5/&44 

Prelude> hypo'
asd
*** Exception: Prelude.undefined

8IZ #FDBVTF UIJT MJUUMF seq GVODUJPO NBHJDBMMZ GPSDFT FWBM


VBUJPO PG UIF ƶSTU BSHVNFOU JG BOE XIFO UIF TFDPOE BSHVNFOU
IBT UP CF FWBMVBUFE "EEJOH seq NFBOT UIBU BOZUJNF Ԣ JT FWBMV
BUFE ԧ NVTU BMTP CF FWBMVBUFE 8FƊMM HFU JOUP NPSF EFUBJM JO B
NPNFOU
0OF UIJOH UP OPUF CFGPSF XF JOWFTUJHBUF seq JT UIBU XF NBO
BHFE UP SVO getLine CFGPSF UIF CPUUPN HPU FWBMVBUFE TP UIJT
TUJMM JTOƊU RVJUF XIBU B TUSJDU MBOHVBHF XPVMEƊWF EPOF $BTF
FYQSFTTJPOT BSF JO HFOFSBM HPJOH UP GPSDF FWBMVBUJPO 5IJT
NBLFT TFOTF JG ZPV SFBMJ[F JU IBT UP FWBMVBUF UIF FYQSFTTJPO UP
EJTDSJNJOBUF PO UIF DBTFT " TNBMM FYBNQMF UP EFNPOTUSBUF

let b = ???
case b of
True -> ...
False

)FSF ԑ DPVME CF QSFUUZ NVDI BOZUIJOH *U NVTU FWBMVBUF ԑ


UP ƶOE PVU JG UIF FYQSFTTJPO SFTVMUT JO 5SVF PS 'BMTF
$)"15&3  /0/453*$5/&44 

TFR BOE ZF TIBMM ƶOE


#FGPSF XF NPWF BOZ GVSUIFS XJUI NBLJOH )BTLFMM TUSJDUFS MFUƊT
UBML BCPVU seq B MJUUMF CJU 0OF UIJOH JT UIBU UIF UZQF JT VI B CJU
XFJSE

seq :: a -> b -> b

$MFBSMZ UIFSFƊT NPSF HPJOH PO IFSF UIBO flip const *U NJHIU


IFMQ UP LOPX UIBU JO TPNF WFSZ PME WFSTJPOT PG )BTLFMM JU VTFE
UP IBWF UIF UZQF

seq :: Eval a => a -> b -> b

Eval JT TIPSU GPS ƌFWBMVBUJPO UP XFBL IFBE OPSNBM GPSN ƍ


BOE JU QSPWJEFE B NFUIPE GPS GPSDJOH FWBMVBUJPO *OTUBODFT
XFSF QSPWJEFE GPS BMM UIF UZQFT JO base *U XBT FMJEFE JO QBSU TP
ZPV DPVME VTF seq JO ZPVS DPEF XJUIPVU DIVSOJOH ZPVS QPMZ
NPSQIJD UZQF WBSJBCMFT BOE GPSDJOH B CVODI PG DIBOHFT 8JUI
SFTQFDU UP CPUUPN seq JT EFƶOFE BT CFIBWJOH JO UIF GPMMPXJOH
NBOOFS

seq bottom b = bottom


seq literallyAnythingNotBottom b = b

/PX XIZ EPFT seq MPPL MJLF constƊT HBXLZ DPVTJO #FDBVTF
FWBMVBUJPO JO )BTLFMM JT EFNBOE ESJWFO XF DBOƊU HVBSBOUFF UIBU
TPNFUIJOH XJMM FWFS CF FWBMVBUFE QFSJPE *OTUFBE XF IBWF UP
$)"15&3  /0/453*$5/&44 

DSFBUF MJOLT CFUXFFO OPEFT JO UIF HSBQI PG FYQSFTTJPOT XIFSF


GPSDJOH POF FYQSFTTJPO XJMM GPSDF ZFU BOPUIFS FYQSFTTJPO -FUƊT
MPPL BU BOPUIFS FYBNQMF

Prelude> let wc x z = let y = undefined `seq` 'y' in x


Prelude> foldr wc 'z' ['a'..'e']
'a'
Prelude> foldr (flip wc) 'z' ['a'..'e']
'z'

8F OFWFS FWBMVBUFE Ԩ TP XF OFWFS GPSDFE UIF CPUUPN )PX


FWFS XF DBO MBTI ZFU BOPUIFS EBUB EFQFOEFODZ GSPN Ԩ UP ԧ

Prelude> let bot = undefined


Prelude> let wc x z = let y = bot `seq` 'y' in y `seq` x
Prelude> foldr wc 'z' ['a'..'e']
*** Exception: Prelude.undefined
Prelude> foldr (flip wc) 'z' ['a'..'e']
*** Exception: Prelude.undefined

1SFWJPVTMZ UIF FWBMVBUJPO EFQFOEFODZ XBT CFUXFFO UIF


CPUUPN WBMVF BOE Ԩ

undefined `seq` y

-- forcing y necessarily forces undefined

y -> undefined
$)"15&3  /0/453*$5/&44 

$IBOHJOH UIF FYQSFTTJPO BT XF EJE DBVTFE UIF GPMMPXJOH UP


IBQQFO

undefined `seq` y `seq` x

-- forcing x necessarily forces y


-- forcing y necessarily forces undefined

x -> y -> undefined

8F UIJOL PG UIJT BT B ƌDIBJO SFBDUJPOƍ


"MM XF DBO EP JT DIVDL B MJGFSBǒ GSPN POF WBMVF UP BOPUIFS
BT B NFBOT PG TBZJOH ƌJG ZPV XBOU UP HFU IJN ZPV HPUUB HFU
UISPVHI NFƍ 8F DBO FWFO TFU PVS MJGFSBǒ CVEEJFT BESJǒ
$IFDL JU PVU

notGonnaHappenBru :: Int
notGonnaHappenBru =
let x = undefined
y = 2
z = (x `seq` y `seq` 10, 11)
in snd z

5IF BCPWF XJMM OPU CPUUPN PVU 0VS MJGFSBǒ CVEEJFT BSF
CPCCJOH JO UIF PDFBO CMVF XJUI OP UVHCPBU FWBMVBUPS UP QVMM
UIFN JO
$)"15&3  /0/453*$5/&44 

TFR BOE XFBL IFBE OPSNBM GPSN


8IBU seq EPFT JT FWBMVBUF ZPVS FYQSFTTJPO VQ UP XFBL IFBE OPS
NBM GPSN 8FƊWF EJTDVTTFE JU CFGPSF CVU JG ZPVƊE MJLF B EFFQFS
JOWFTUJHBUJPO BOE DPOUSBTU PG XFBL IFBE OPSNBM GPSN BOE OPS
NBM GPSN XF TUSPOHMZ SFDPNNFOE 4JNPO .BSMPXƊT ƌ1BSBMMFM
BOE $PODVSSFOU 1SPHSBNNJOH JO )BTLFMMƍ  8)/' FWBMVBUJPO
NFBOT JU TUPQT BU UIF ƶSTU EBUB DPOTUSVDUPS PS MBNCEB -FUƊT
UFTU UIBU IZQPUIFTJT

Prelude> let dc = (,) undefined undefined


Prelude> let noDc = undefined
Prelude> let lam = \_ -> undefined
Prelude> dc `seq` 1
1
Prelude> noDc `seq` 1
*** Exception: Prelude.undefined
Prelude> lam `seq` 1
1

3JHIUP /P TVSQSJTFT SJHIU 3JHIU 0LBZ


4JODF dc IBT B EBUB DPOTUSVDUPS seq EPFTOƊU OFFE UP DBSF
BCPVU UIF WBMVFT JOTJEF UIBU DPOTUSVDUPS XFBL IFBE OPSNBM
GPSN FWBMVBUJPO POMZ SFRVJSFT JU UP FWBMVBUF UIF DPOTUSVDUPS
0O UIF PUIFS IBOE noDc IBT OP EBUB DPOTUSVDUPS PS MBNCEB
PVUTJEF UIF WBMVF TP UIFSFƊT OP IFBE GPS UIF FWBMVBUJPO UP TUPQ

http://chimera.labs.oreilly.com/books/1230000000929
$)"15&3  /0/453*$5/&44 

BU 'JOBMMZ lam IBT B MBNCEB PVUTJEF UIF FYQSFTTJPO XIJDI IBT
UIF TBNF FƵFDU PO FWBMVBUJPO BT B EBUB DPOTUSVDUPS EPFT

$BTF NBUDIJOH BMTP DIBJOT FWBMVBUJPO


5IJT GPSDJOH CFIBWJPS IBQQFOT BMSFBEZ XJUIPVU seq 'PS FY
BNQMF XIFO ZPV DBTF PS QBUUFSO NBUDI PO TPNFUIJOH ZPVƊSF
GPSDJOH UIF WBMVF ZPV QBUUFSO NBUDIFE PO CFDBVTF JU EPFTOƊU
LOPX XIJDI EBUB DPOTUSVDUPS JT SFMFWBOU VOUJM JU JT FWBMVBUFE
UP UIF EFQUI SFRVJSFE UP ZJFME UIF EFQUI PG EBUB DPOTUSVDUPST
ZPV QBUUFSO NBUDIFE -FUƊT MPPL BU BO FYBNQMF

data Test =
A Test2
| B Test2
deriving (Show)

data Test2 =
C Int
| D Int
deriving (Show)
$)"15&3  /0/453*$5/&44 

forceNothing :: Test -> Int


forceNothing _ = 0

forceTest :: Test -> Int


forceTest (A _) = 1
forceTest (B _) = 2

forceTest2 :: Test -> Int


forceTest2 (A (C i)) = i
forceTest2 (B (C i)) = i
forceTest2 (A (D i)) = i
forceTest2 (B (D i)) = i

8FƊMM UFTU forceNothing ƶSTU

Prelude> forceNothing undefined


0
Prelude> forceNothing (A undefined)
0

*UƊMM OFWFS CPUUPN PVU CFDBVTF JU OFWFS GPSDFT BOZUIJOH *UƊT


KVTU B DPOTUBOU WBMVF UIBU ESPQT JUT BSHVNFOU PO UIF ƷPPS 8IBU
BCPVU forceTest

Prelude> forceTest (A undefined)


1
Prelude> forceTest (B undefined)
$)"15&3  /0/453*$5/&44 

2
Prelude> forceTest undefined
*** Exception: Prelude.undefined

8F POMZ HFU B CPUUPN XIFO UIF PVUFSNPTU 5FTU WBMVF JT


CPUUPN CFDBVTF UIBUƊT UIF POMZ WBMVF XIPTF EBUB DPOTUSVDUPST
XFƊSF DBTJOH PO "OE UIFO XJUI forceTest2

Prelude> forceTest2 (A (C 0))


0
Prelude> forceTest2 (A (C undefined))
*** Exception: Prelude.undefined

Prelude> forceTest2 (A undefined)


*** Exception: Prelude.undefined

Prelude> forceTest2 undefined


*** Exception: Prelude.undefined

5IFSF XF HP PVUTJEF  JO

$PSF %VNQ
/PU UIF VTVBM DPSF EVNQ ZPV NJHIU CF UIJOLJOH PG *O UIJT
DBTF XFƊSF UBMLJOH BCPVU UIF VOEFSMZJOH MBOHVBHF UIBU ()$
)BTLFMM HFUT TJNQMJƶFE UP BǒFS UIF DPNQJMFS IBT EFTVHBSFE PVS
DPEF
$)"15&3  /0/453*$5/&44 

0VS ƶSTU NFBOT PG EFUFSNJOJOH TUSJDUOFTT XBT CZ JOKFDUJOH


CPUUPNT JOUP PVS FYQSFTTJPOT BOE PCTFSWJOH UIF FWBMVBUJPO
*OKFDUJOH CPUUPNT FWFSZXIFSF BMMPXT VT UP TFF DMFBSMZ XIBUƊT
CFJOH FWBMVBUFE TUSJDUMZ BOE XIBUƊT OPU 0VS TFDPOE NFBOT PG
EFUFSNJOJOH TUSJDUOFTT JO )BTLFMM JT FYBNJOJOH ()$ $PSF 
)FSFƊT UIF FYBNQMF XFƊMM CF XPSLJOH XJUI

module CoreDump where

discriminatory :: Bool -> Int


discriminatory b =
case b of
False -> 0
True -> 1

-PBE UIJT VQ JO ()$J JO UIF GPMMPXJOH NBOOFS

Prelude> :set -ddump-simpl


Prelude> :l code/coreDump.hs
[1 of 1] Compiling CoreDump

==================== Tidy Core ====================


... some noise...

:PV TIPVME UIFO HFU UIF GPMMPXJOH ()$ $PSF PVUQVU



https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/CoreSynType
$)"15&3  /0/453*$5/&44 

discriminatory :: Bool -> Int


[GblId, Arity=1, Caf=NoCafRefs, Str=DmdType]
discriminatory =
\ (b_aZJ :: Bool) ->
case b_aZJ of _ [Occ=Dead] {
False -> GHC.Types.I# 0;
True -> GHC.Types.I# 1
}

()$ $PSF JT VHMZ 8FƊSF OPU HPJOH UP EJTTFNCMF BCPVU UIJT


)PXFWFS UIFSF BSF TPNF NFBOT PG DMFBOJOH JU VQ 0OF JT UP
VTF UIF -dsuppress-all ƷBH

Prelude> :set -dsuppress-all


Prelude> :r

/PUF UIBU ZPV NBZ OFFE UP QPLF UIF ƶMF UP GPSDF JU UP SFMPBE
5IJT UIFO PVUQVUT

discriminatory
discriminatory =
\ b_aZY ->
case b_aZY of _ {
False -> I# 0;
True -> I# 1
}
$)"15&3  /0/453*$5/&44 

" UJUDI NPSF SFBEBCMF 5IF JEFB IFSF JT UIBU UIF TJNQMFS
$PSF MBOHVBHF HJWFT VT B DMFBSFS JEFB PG XIFO QSFDJTFMZ TPNF
UIJOH XJMM CF FWBMVBUFE 'PS UIF TBLF PG TJNQMJDJUZ XFƊMM SFWJTJU
B QSFWJPVT FYBNQMF

forceNothing _ = 0

*O $PSF JU MPPLT MJLF UIJT

forceNothing = \ _ -> I# 0#

8FƊSF MPPLJOH GPS DBTF FYQSFTTJPOT JO ()$ $PSF UP ƶOE PVU


XIFSF UIF TUSJDUOFTT JT JO PVS DPEF CFDBVTF DBTF FYQSFTTJPOT
NVTU CF FWBMVBUFE 5IFSF BSFOƊU BOZ DBTFT IFSF TP JU GPSDFT
TUSJDUMZ OPUIJOH 5IF I# O# JT UIF VOEFSMZJOH SFQSFTFOUBUJPO
PG BO *OU MJUFSBM XIJDI JT FYQPTFE JO ()$ $PSF 0O XJUI UIF
TIPX
-FUƊT TFF XIBU UIF $PSF GPS forceTest MPPLT MJLF

forceTest =
\ ds_d2oX ->
case ds_d2oX of _ {
A ds1_d2pI -> I# 1#;
B ds1_d2pJ -> I# 2#
}

)""""""""""""
$)"15&3  /0/453*$5/&44 

'SPN UIF ()$ $PSF GPS UIJT XF DBO TFF UIBU XF GPSDF POF
WBMVF UIF PVUFSNPTU EBUB DPOTUSVDUPST PG UIF 5FTU UZQF 5IF
DPOUFOUT PG UIPTF EBUB DPOTUSVDUPST BSF HJWFO B OBNF CVU OFWFS
VTFE BOE TP BSF OFWFS FWBMVBUFE

forceTest2 =
\ ds_d2n2 ->
case ds_d2n2 of _ {
A ds1_d2oV ->
case ds1_d2oV of _ {
C i_a1lo -> i_a1lo;
D i_a1lq -> i_a1lq
};
B ds1_d2oW ->
case ds1_d2oW of _ {
C i_a1lp -> i_a1lp;
D i_a1lr -> i_a1lr
}
}

8JUI forceTest2 UIF PVUTJEFOFTT BOE JOTJEFOFTT TIPXT NPSF


DMFBSMZ *O UIF PVUFS QBSU PG UIF GVODUJPO XF EP UIF TBNF BT
forceTest CVU UIF EJƵFSFODF JT UIBU XF FOE VQ BMTP GPSDJOH UIF
DPOUFOUT PG UIF PVUFS 5FTU EBUB DPOTUSVDUPST 5IF GVODUJPO IBT
GPVS QPTTJCMF SFTVMUT UIBU BSFOƊU CPUUPN BOE JG JU JTOƊU QBTTFE CPU
UPN JUƊMM BMXBZT GPSDF UXJDF 0ODF GPS 5FTU BOE PODF GPS 5FTU
$)"15&3  /0/453*$5/&44 

*U SFUVSOT CVU EPFT OPU JUTFMG GPSDF PS FWBMVBUF UIF DPOUFOUT PG


UIF 5FTU EBUB DPOTUSVDUPS
*O $PSF B DBTF FYQSFTTJPO BMXBZT FWBMVBUFT XIBU JU DBTFT PO ƈ
FWFO JG OP QBUUFSO NBUDIJOH JT QFSGPSNFE XIFSFBT JO )BTLFMM
QSPQFS WBMVFT BSF GPSDFE XIFO NBUDIJOH PO EBUB DPOTUSVDUPST
8F SFDPNNFOE SFBEJOH UIF ()$ EPDVNFOUBUJPO PO UIF $PSF
MBOHVBHF JO UIF GPPUOPUF BCPWF JG ZPVƊE MJLF UP MFWFSBHF $PSF
UP VOEFSTUBOE ZPVS )BTLFMM DPEFƊT QFSGPSNBODF PS CFIBWJPS
NPSF EFFQMZ /PX MFU VT VTF UIJT UP BOBMZ[F TPNFUIJOH

discriminatory :: Bool -> Int


discriminatory b =
let x = undefined
in case b of
False -> 0
True -> 1

8IBU EPFT UIF $PSF GPS UIJT MPPL MJLF

discriminatory
discriminatory =
\ b_a10c ->
case b_a10c of _ {
False -> I# 0;
True -> I# 1
}
$)"15&3  /0/453*$5/&44 

()$ JT UPP DMFWFS GPS PVS TIFOBOJHBOT *U LOPXT XFƊMM OFWFS


FWBMVBUF ԧ TP JU ESPQT JU 8IBU JG XF GPSDF JU UP FWBMVBUF ԧ CFGPSF
XF FWBMVBUF ԑ

discriminatory :: Bool -> Int


discriminatory b =
let x = undefined
in case x `seq` b of
False -> 0
True -> 1

5IFO UIF $PSF

discriminatory =
\ b_a10D ->
let {
x_a10E
x_a10E = undefined } in
case
case x_a10E of _ {
__DEFAULT -> b_a10D
} of _ {
False -> I# 0;
True -> I# 1
}
$)"15&3  /0/453*$5/&44 

8IBUƊT IBQQFOFE IFSF JT UIBU UIFSF BSF OPX UXP DBTF FY
QSFTTJPOT POF OFTUFE JO BOPUIFS 5IF OFTUJOH JT UP NBLF UIF
FWBMVBUJPO PG ԧ PCMJHBUPSZ CFGPSF FWBMVBUJOH ԑ 5IJT JT IPX seq
DIBOHFT ZPVS DPEF

" $PSF EJƵFSFODF *O )BTLFMM DBTF NBUDIJOH JT TUSJDU ƈ PS BU


MFBTU UIF QBUUFSO NBUDIJOH PG JU JT ƈ VQ UP 8)/' *O $PSF
DBTFT BSF BMXBZT TUSJDU UP 8)/' 5IJT EPFTOƊU TFFN UP CF B EJT
UJODUJPO UIBU NBUUFST CVU UIFSF BSF UJNFT XIFO UIF EJTUJODUJPO
CFDPNFT SFMFWBOU *O )BTLFMM UIJT XJMM OPU CPUUPN PVU

case undefined of { _ -> False}

8IFO UIBU HFUT USBOTMJUFSBUFE JOUP $PSF JU SFDPHOJ[FT UIBU


XF EJEOƊU BDUVBMMZ VTF UIF DBTF NBUDI GPS BOZUIJOH BOE ESPQT
UIF DBTF FYQSFTTJPO FOUJSFMZ TJNQMJGZJOH JU UP KVTU UIF EBUB
DPOTUSVDUPS 'BMTF
)PXFWFS UIJT $PSF FYQSFTTJPO JT TZOUBDUJDBMMZ TJNJMBS UP UIF
)BTLFMM BCPWF CVU JU XJMM CPUUPN PVU

case undefined of { DEFAULT -> False }

$BTF JO $PSF JT TUSJDU FWFO JG UIFSFƊT POF DBTF BOE JU EPFTOƊU


NBUDI PO BOZUIJOH $PSF BOE )BTLFMM BSF OPU UIF TBNF MBO
HVBHF CVU BOZUJNF ZPV OFFE UP LOPX JG UXP FYQSFTTJPOT JO

https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/CoreSynType#
Caseexpressions
$)"15&3  /0/453*$5/&44 

)BTLFMM BSF UIF TBNF POF XBZ UP LOPX GPS TVSF JT CZ FYBNJOJOH
UIF $PSF

" MJUUMF CJU TUSJDUFS OPX


0LBZ XF IBE B OJDF MJUUMF EJHSFTTJPO UIFSF JOUP XPOEFSMBOE
-FUƊT HFU CBDL UP UIF QPJOU XIJDI JTƒXF TUJMM IBWFOƊU RVJUF NBO
BHFE UP BDDPNQMJTI XIBU B TUSJDU MBOHVBHF XPVME IBWF EPOF
XJUI PVS hypo GVODUJPO CFDBVTF XF EJE QBSUJBMMZ FWBMVBUF UIF
FYQSFTTJPO 8F FWBMVBUFE UIF Ԣ XIJDI GPSDFE UIF ԧ XIJDI JT
XIBU ƶOBMMZ HBWF VT UIF FYDFQUJPO " TUSJDU MBOHVBHF XPVME OPU
FWFO IBWF FWBMVBUFE Ԣ CFDBVTF FWBMVBUJOH Ԣ XPVME EFQFOE PO
UIF ԧ JOTJEF BMSFBEZ CFJOH FWBMVBUFE
8IBU JG XF XBOU PVS )BTLFMM QSPHSBN UP EP BT B TUSJDU MBO
HVBHF XPVMEƊWF EPOF

hypo'' :: IO ()
hypo'' = do
let x :: Integer
x = undefined
s <- x `seq` getLine
case s of
"hi" -> print x
_ -> putStrLn "hello"

/PUJDF XF NPWFE UIF seq UP UIF ƌFBSMJFTUƍ QPTTJCMF QPJOU


JO PVS *0 BDUJPO 5IJT POFƊMM KVTU QPQ XJUIPVU TP NVDI BT B
$)"15&3  /0/453*$5/&44 

CZZPVSMFBWF

Prelude> hypo''
*** Exception: Prelude.undefined

5IF SFBTPO JT UIBU XFƊSF GPSDJOH FWBMVBUJPO PG UIF CPUUPN


CFGPSF XF FWBMVBUF getLine XIJDI XPVME IBWF QFSGPSNFE UIF
FƵFDU PG BXBJUJOH VTFS JOQVU 8IJMF UIJT SFQSPEVDFT UIF PC
TFSWBCMF SFTVMUT PG XIBU B TUSJDU MBOHVBHF NJHIU IBWF EPOF
JU JTOƊU USVMZ UIF TBNF UIJOH CFDBVTF XFƊSF OPU ƶSJOH PƵ UIF
FSSPS VQPO UIF DPOTUSVDUJPO PG UIF CPUUPN *UƊT OPU QPTTJCMF GPS
BO FYQSFTTJPO UP CF FWBMVBUFE VOUJM UIF QBUI FWBMVBUJPO UBLFT
UISPVHI ZPVS QSPHSBN SFBDIFT UIBU FYQSFTTJPO *O )BTLFMM UIF
USFF EPFTOƊU GBMM JO UIF XPPET VOUJM ZPV XBML UISPVHI UIF GPSFTU
BOE HFU UP UIF USFF 'PS UIBU NBUUFS UIF USFF EJEOƊU FYJTU VOUJM
ZPV XBMLFE VQ UP JU

&YFSDJTFT &WBMVBUF
&YQBOE UIF FYQSFTTJPO JO BT NVDI EFUBJM BT QPTTJCMF 5IFO
XPSL PVUTJEFJO UP TFF XIBU UIF FYQSFTTJPO FWBMVBUFT UP

 const 1 undefined

 const undefined 1

 flip const undefined 1


$)"15&3  /0/453*$5/&44 

 flip const 1 undefined

 const undefined undefined

 foldr const 'z' ['a'..'e']

 foldr (flip const) 'z' ['a'..'e']

 $BMM CZ OBNF DBMM CZ OFFE


"OPUIFS XBZ XF DBO UBML BCPVU EJƵFSFOU FWBMVBUJPO TUSBUFHJFT
JT CZ EJTUJOHVJTIJOH UIFN PO UIF CBTJT PG DBMM CZ OBNF DBMM CZ
OFFE BOE DBMM CZ WBMVF

 $BMM CZ WBMVF "SHVNFOU FYQSFTTJPOT IBWF CFFO FWBMVBUFE


CFGPSF FOUFSJOH B GVODUJPO 5IF FYQSFTTJPOT UIBU CJOEJOHT
SFGFSFODF BSF FWBMVBUFE CFGPSF DSFBUJOH UIF CJOEJOH 5IJT
JT DPOWFOUJPOBMMZ DBMMFE TUSJDU 5IJT JT JOTJEFPVU FWBMVB
UJPO

 $BMM CZ OBNF &YQSFTTJPOT DBO CF BSHVNFOUT UP B GVODUJPO


XJUIPVU IBWJOH CFFO FWBMVBUFE PS JO TPNF DBTFT OFWFS
CFJOH FWBMVBUFE :PV DBO DSFBUF CJOEJOHT UP FYQSFTTJPOT
XJUIPVU FWBMVBUJOH UIFN ƶSTU /POTUSJDUOFTT JODMVEFT UIJT
FWBMVBUJPO TUSBUFHZ 5IJT JT PVUTJEFJO

 $BMM CZ OFFE 5IJT JT UIF TBNF BT DBMM CZ OBNF CVU FYQSFT


TJPOT BSF POMZ FWBMVBUFE PODF 5IJT POMZ IBQQFOT TPNF
$)"15&3  /0/453*$5/&44 

PG UIF UJNF JO ()$ )BTLFMM VTVBMMZ XIFO BO FYQSFTTJPO


JTOƊU B MBNCEB UIBU UBLFT BSHVNFOUT BOE BMTP IBT B OBNF
3FTVMUT BSF UZQJDBMMZ TIBSFE XJUIJO UIBU OBNF POMZ JO ()$
)BTLFMM UIBU JT PUIFS JNQMFNFOUBUJPOT PG )BTLFMM NBZ
DIPPTF UP EP UIJOHT EJƵFSFOUMZ
 5IJT JT BMTP OPOTUSJDU
BOE PVUTJEFJO

 /POTUSJDU FWBMVBUJPO DIBOHFT


XIBU XF DBO EP
8FƊMM DPWFS OPSNBM PSEFS FWBMVBUJPO UIF OPOTUSJDU TUSBUFHZ
)BTLFMM QSFTDSJCFT GPS JUT JNQMFNFOUBUJPOT
JO NPSF EFUBJM MBUFS
/PX XFƊMM MPPL BU FYBNQMFT PG XIBU OPOTUSJDUOFTT FOBCMFT
5IF GPMMPXJOH XJMM XPSL JO MBOHVBHFT XJUI B TUSJDU PS B OPO
TUSJDU FWBMVBUJPO TUSBUFHZ

Prelude> let myList = [1, 2, 3]


Prelude> tail myList
[2,3]

5IBU XPSLT JO FJUIFS TUSJDU PS OPOTUSJDU MBOHVBHFT CFDBVTF


UIFSF JT OPUIJOH UIFSF UIBU DBOƊU CF FWBMVBUFE )PXFWFS JG XF
LFFQ JO NJOE UIBU undefined BT BO JOTUBODF PG CPUUPN XJMM UISPX
BO FSSPS XIFO GPSDFE

Prelude> undefined
*** Exception: Prelude.undefined
$)"15&3  /0/453*$5/&44 

8FƊMM TFF B EJƵFSFODF CFUXFFO TUSJDU BOE OPOTUSJDU 5IJT


XJMM POMZ XPSL JO MBOHVBHFT UIBU BSF OPOTUSJDU

Prelude> let myList = [undefined, 2, 3]


Prelude> tail myList
[2,3]

" TUSJDU MBOHVBHF XPVME IBWF DSBTIFE PO DPOTUSVDUJPO PG


myList EVF UP UIF QSFTFODF PG CPUUPN 5IJT JT CFDBVTF TUSJDU
MBOHVBHFT FBHFSMZ FWBMVBUF BMM FYQSFTTJPOT BT TPPO BT UIFZ
BSF DPOTUSVDUFE 5IF NPNFOU [undefined, 2, 3] XBT EFDMBSFE
undefined XPVMEƊWF CFFO FWBMVBUFE BT BO BSHVNFOU UP (:) BOE
SBJTFE UIF FYDFQUJPO *O )BTLFMM IPXFWFS OPOTUSJDU FWBMVB
UJPO NFBOT UIBU CPUUPN WBMVF XPOƊU CF FWBMVBUFE VOMFTT JU JT
OFFEFE GPS TPNF SFBTPO
5BLF B MPPL BU UIF OFYU FYBNQMF BOE CFGPSF HPJOH PO TFF
JG ZPV DBO ƶHVSF PVU XIFUIFS JU XJMM UISPX BO FYDFQUJPO BOE
XIZ

Prelude> head $ sort [1, 2, 3, undefined]

8IFO XF DBMM head PO B MJTU UIBU IBT CFFO QBTTFE UP sort XF


POMZ OFFE UIF MPXFTU WBMVF JO UIF MJTU BOE UIBUƊT BMM UIF XPSL XF
XJMM EP 5IF QSPCMFN JT UIBU JO PSEFS GPS sort UP LOPX XIBU UIF
MPXFTU WBMVF JT JU NVTU FWBMVBUF undefined XIJDI UIFO UISPXT
UIF FSSPS
$)"15&3  /0/453*$5/&44 

 5IVOL -JGF


" UIVOL JT VTFE UP SFGFSFODF TVTQFOEFE DPNQVUBUJPOT UIBU
NJHIU CF QFSGPSNFE PS DPNQVUFE BU B MBUFS QPJOU JO ZPVS QSP
HSBN :PV DBO HFU JOUP DPOTJEFSBCMZ NPSF EFUBJM PO UIJT UPQJD
CVU FTTFOUJBMMZ UIVOLT BSF DPNQVUBUJPOT OPU ZFU FWBMVBUFE VQ
UP XFBL IFBE OPSNBM GPSN *G ZPV SFBE UIF ()$ OPUFT PO UIJT
ZPVƊMM TFF SFGFSFODFT UP IFBE OPSNBM GPSN ƈ JUƊT UIF TBNF UIJOH
BT XFBL IFBE OPSNBM GPSN

/PU BMM WBMVFT HFU UIVOLFE


8FƊSF HPJOH UP CF VTJOH UIF ()$J DPNNBOE sprint JO UIJT
TFDUJPO BT POF NFBOT PG TIPXJOH XIFO TPNFUIJOH JT UIVOLFE
:PV NBZ SFNFNCFS UIJT GSPN UIF -JTUT DIBQUFS CVU MFUƊT SFGSFTI
PVS NFNPSJFT B CJU
5IF sprint DPNNBOE BMMPXT VT UP TIPX XIBU IBT CFFO FWBM
VBUFE BMSFBEZ CZ QSJOUJOH JO UIF 3&1- "O VOEFSTDPSF JT VTFE
UP SFQSFTFOU WBMVFT UIBU IBWFOƊU CFFO FWBMVBUFE ZFU 8F OPUFE
CFGPSF UIBU UIJT DPNNBOE DBO IBWF TPNF RVJSLZ CFIBWJPS BM
UIPVHI UIJT DIBQUFS XJMM FYQMBJO TPNF PG UIF UIJOHT UIBU DBVTF
UIPTF TFFNJOHMZ VOQSFEJDUBCMF CFIBWJPST
-FUƊT TUBSU XJUI B TJNQMF FYBNQMF

Prelude> let myList = [1, 2, 3] :: [Integer]



https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/HeapObjects
$)"15&3  /0/453*$5/&44 

Prelude> :sprint myList


myList = [1,2,3]

8BJU B TFDPOE ƈ XIBU IBQQFOFE IFSF 8IZ JT UIF MJTU TIPXO


GVMMZ FWBMVBUFE XIFO JUƊT OPU CFFO OFFEFE CZ BOZUIJOH 5IJT
JT BO PQQPSUVOJTUJD TUSJDUOFTT ()$ XJMM OPU UIVOL BOE UIVT
EFMBZ
WBMVFT XIJDI BSF NFSFMZ EBUB DPOTUSVDUPST %BUB DPO
TUSVDUPST BSF LOPXO UP CF DPOTUBOU XIJDI KVTUJƶFT UIF TBGFUZ
PG UIF PQUJNJ[BUJPO 5IF EBUB DPOTUSVDUPST IFSF BSF DPOT (:)
UIF *OUFHFST BOE UIF FNQUZ MJTU ƈ BMM PG UIFN BSF DPOTUBOUT

#VU BSFOƊU EBUB DPOTUSVDUPST GVODUJPOT %BUB DPOTUSVDUPST


BSF MJLF GVODUJPOT XIFO UIFZƊSF VOBQQMJFE BOE DPOTUBOUT PODF
UIFZ BSF GVMMZ BQQMJFE 4JODF BMM UIF EBUB DPOTUSVDUPST JO UIF
BCPWF FYBNQMF BSF GVMMZ BQQMJFE BMSFBEZ FWBMVBUJOH UP XFBL
IFBE OPSNBM GPSN NFBOT FWBMVBUJOH FWFSZUIJOH CFDBVTF UIFSFƊT
OPUIJOH MFǒ UP BQQMZ
/PX CBDL UP UIF UIVOLFSZ
" HSBQI PG UIF WBMVFT PG myList MPPLT MJLF

myList
|
:
/ \
1 :
/ \
$)"15&3  /0/453*$5/&44 

2 :
/ \
3 []

)FSF UIFSF BSFOƊU BOZ VOFWBMVBUFE UIVOLT JUƊT KVTU UIF ƶOBM
WBMVFT UIBU IBWF CFFO SFNFNCFSFE )PXFWFS JG XF NBLF JU
NPSF QPMZNPSQIJD

Prelude> let myList2 = [1, 2, 3]


Prelude> :t myList2
myList2 :: Num t => [t]
Prelude> :sprint myList2
myList2 = _

XFƊMM TFF BO VOFWBMVBUFE UIVOL SFQSFTFOUFE CZ UIF VOEFS


TDPSF BU UIF WFSZ UPQ MFWFM PG UIF FYQSFTTJPO 4JODF UIF UZQF
JT OPU DPODSFUF UIFSFƊT BO JNQMJDJU GVODUJPO Num a -> a VOEFS
OFBUI BXBJUJOH BQQMJDBUJPO UP TPNFUIJOH UIBU XJMM GPSDF JU UP
FWBMVBUF UP B DPODSFUF UZQF 5IFSFƊT OPUIJOH IFSF USJHHFSJOH
UIBU FWBMVBUJPO TP UIF XIPMF MJTU SFNBJOT BO VOFWBMVBUFE UIVOL
8FƊMM HFU JOUP NPSF EFUBJM BCPVU IPX UZQFDMBTT DPOTUSBJOUT FWBM
VBUF TPPO
()$ XJMM BMTP TUPQ PQQPSUVOJTUJDBMMZ FWBMVBUJOH BT TPPO BT
JU IJUT B DPNQVUBUJPO

Prelude> let myList = [1, 2, id 1] :: [Integer]


Prelude> :sprint myList
$)"15&3  /0/453*$5/&44 

myList = [1,2,_]

*UƊT B USJWJBM DPNQVUBUJPO CVU ()$J DPOWFOJFOUMZ MFBWFT JU


CF )FSFƊT UIF UIVOL HSBQI GPS UIF BCPWF

myList
|
:
/ \
1 :
/ \
2 :
/ \
_ []

/PX MFU VT DPOTJEFS BOPUIFS DBTF UIBU NJHIU CF TMJHIUMZ


DPOGVTJOH JOJUJBMMZ GPS TPNF

Prelude> let myList = [1, 2, id 1] :: [Integer]


Prelude> let myList' = myList ++ undefined
Prelude> :sprint myList'
myList' = _

8IPB XIPB XIPB 8IBUƊT HPJOH PO IFSF 5IF XIPMF UIJOH


JT UIVOLFE CFDBVTF JUƊT OPU JO XFBL IFBE OPSNBM GPSN 8IZ
JTOƊU JU JO XFBL IFBE OPSNBM GPSN BMSFBEZ #FDBVTF UIF PVU
FSNPTU UFSN JTOƊU B EBUB DPOTUSVDUPS MJLF (:) 5IF PVUFSNPTU
UFSN JT UIF GVODUJPO (++)
$)"15&3  /0/453*$5/&44 

myList' = (++) _ _

5IF GVODUJPO JT PVUFSNPTU EFTQJUF UIF GBDU UIBU JU JT TVQFS


ƶDJBMMZ BO JOƶY PQFSBUPS CFDBVTF UIF GVODUJPO JT UIF MBNCEB
5IF BSHVNFOUT BSF QBTTFE JOUP UIF GVODUJPO CPEZ UP CF FWBMV
BUFE

 4IBSJOH JT DBSJOH


4IBSJOH IFSF SPVHIMZ NFBOT XIBU XFƊWF JNQMJFE BCPWF UIBU
XIFO B DPNQVUBUJPO JT OBNFE UIF SFTVMUT PG FWBMVBUJOH UIBU
DPNQVUBUJPO DBO CF TIBSFE CFUXFFO BMM SFGFSFODFT UP UIBU OBNF
XJUIPVU SFFWBMVBUJOH JU 8F DBSF BCPVU TIBSJOH CFDBVTF NFN
PSZ JT ƶOJUF FWFO UPEBZ JO UIF MBOE PG DIJDLFOT JO FWFSZ QPU
BOE TNBSUQIPOFT JO FWFSZ QPDLFU 5IF JEFB IFSF JT UIBU OPO
TUSJDUOFTT JT B ƶOF UIJOH CVU DBMMCZOBNF TFNBOUJDT BSFOƊU
BMXBZT FOPVHI UP NBLF JU TVƸDJFOUMZ FƸDJFOU 8IBU JT TVƸ
DJFOUMZ FƸDJFOU 5IBU EFQFOET PO DPOUFYU BOE XIFUIFS JUƊT
ZPVS EJTTFSUBUJPO PS OPU
0OF PG UIF QPJOUT PG DPOGVTJPO GPS QFPQMF XIFO USZJOH UP
ƶHVSF PVU IPX ()$ )BTLFMM SFBMMZ SVOT DPEF JT UIBU JU CMJQT
TIBSJOH PO BOE PƵ UIBU JT JU PTDJMMBUFT CFUXFFO DBMMCZOFFE
BOE DBMMCZOBNF
CBTFE PO OFDFTTJUZ BOE XIBU JU UIJOLT XJMM
QSPEVDF GBTUFS DPEF 1BSU PG UIF SFBTPO JU DBO EP UIJT BU BMM
XJUIPVU CSFBLJOH ZPVS DPEF JT CFDBVTF UIF DPNQJMFS LOPXT
XIFO ZPVS DPEF EPFT PS EPFT OPU IBWF FƵFDUT
$)"15&3  /0/453*$5/&44 

6TJOH USBDF UP PCTFSWF TIBSJOH


5IF CBTF MJCSBSZ IBT B NPEVMF OBNFE Debug.Trace UIBU IBT GVOD
UJPOT VTFGVM GPS PCTFSWJOH TIBSJOH 8FƊMM NPTUMZ VTF trace IFSF
CVU GFFM GSFF UP QPLF BSPVOE GPS XIBUFWFS FMTF NJHIU DBUDI
ZPVS GBODZ Debug.Trace JT B NFBOT PG DIFBUJOH UIF UZQF TZTUFN
BOE QVUUJOH B putStrLn XJUIPVU IBWJOH *0 JO UIF UZQF 5IJT JT
EFƶOJUFMZ TPNFUIJOH ZPV XBOU UP SFTUSJDU UP FYQFSJNFOUBUJPO
BOE FEVDBUJPO EP OPU VTF JU BT B MPHHJOH NFDIBOJTN JO QSP
EVDUJPO DPEF ƈ JU XPOƊU EP XIBU ZPV UIJOL )PXFWFS JU EPFT
HJWF VT B DPOWFOJFOU NFBOT PG PCTFSWJOH XIFO UIJOHT FWBMVBUF
-FU VT EFNPOTUSBUF IPX XF DBO VTF UIJT UP TFF XIFO UIJOHT
HFU FWBMVBUFE

Prelude> import Debug.Trace


Prelude> let a = trace "a" 1
Prelude> let b = trace "b" 2
Prelude> a + b
b
a
3

5IJT JTOƊU BO FYBNQMF PG TIBSJOH CVU JU EFNPOTUSBUFT IPX


trace DBO CF VTFE UP PCTFSWF FWBMVBUJPO 8F DBO TFF UIBU ԑ
HPU QSJOUFE ƶSTU CFDBVTF UIBU XBT UIF ƶSTU BSHVNFOU UIBU UIF
BEEJUJPO GVODUJPO FWBMVBUFE CVU ZPV DBOOPU BOE TIPVME OPU
SFMZ PO UIF FWBMVBUJPO PSEFS PG UIF BSHVNFOUT UP BEEJUJPO
$)"15&3  /0/453*$5/&44 

)FSF XFƊSF UBMLJOH BCPVU UIF PSEFS JO XIJDI UIF BSHVNFOUT UP


B TJOHMF BQQMJDBUJPO PG BEEJUJPO BSF GPSDFE OPU BTTPDJBUJWJUZ
:PV DBO DPVOU PO BEEJUJPO CFJOH MFǒ BTTPDJBUJWF CVU XJUIJO
FBDI QBJSJOH XIJDI JO UIF QBJS PG BSHVNFOUT HFUT GPSDFE JT OPU
HVBSBOUFFE
-FUƊT MPPL BU B MPOHFS FYBNQMF BOE TFF IPX JU TIPXT VT XIFSF
UIF FWBMVBUJPOT PDDVS

import Debug.Trace (trace)

inc = (+1)

twice = inc . inc

howManyTimes =
inc (trace "I got eval'd" (1 + 1))
+ twice (trace "I got eval'd" (1 + 1))

howManyTimes' =
let onePlusOne = trace "I got eval'd" (1 + 1)
in inc onePlusOne + twice onePlusOne

Prelude> howManyTimes
I got eval'd
I got eval'd
7
$)"15&3  /0/453*$5/&44 

Prelude> howManyTimes'
I got eval'd
7

$PPM XJUI UIBU JO NJOE MFUƊT UBML BCPVU XBZT UP QSPNPUF


BOE QSFWFOU TIBSJOH

8IBU QSPNPUFT TIBSJOH


,JOEOFTT "MTP OBNFT /BNFT UVSO PVU UP CF B QSFUUZ HPPE
XBZ UP NBLF ()$ TIBSF TPNFUIJOH JG JU DPVMEƊWF PUIFSXJTF
CFFO TIBSFE 'JSTU MFUƊT DPOTJEFS UIF FYBNQMF PG TPNFUIJOH
UIBU XPOƊU HFU TIBSFE

Prelude> import Debug.Trace


Prelude> let x = trace "x" (1 :: Int)
Prelude> let y = trace "y" (1 :: Int)
Prelude> x + y
x
y
2

5IJT TFFNT JOUVJUJWF BOE SFBTPOBCMF CVU UIF WBMVFT PG ԧ


BOE Ԩ DBOOPU CF TIBSFE CFDBVTF UIFZ IBWF EJƵFSFOU OBNFT
4P FWFO UIPVHI UIFZ IBWF UIF TBNF WBMVF UIFZ IBWF UP CF
FWBMVBUFE TFQBSBUFMZ
$)"15&3  /0/453*$5/&44 

()$ EPFT VTF UIJT JOUVJUJPO UIBU ZPVƊMM FYQFDU SFTVMUT UP CF


TIBSFE XIFO UIFZ IBWF UIF TBNF OBNF UP NBLF QFSGPSNBODF
NPSF QSFEJDUBCMF *G XF BEE UXP WBMVFT UIBU IBWF UIF TBNF
OBNF JU XJMM HFU FWBMVBUFE PODF BOE POMZ PODF

Prelude> import Debug.Trace


Prelude> let a = trace "a" (1 :: Int)
Prelude> a + a
a
2
Prelude> a + a
2

*OEJSFDUJPO XPOƊU DIBOHF UIJT FJUIFS

Prelude> let x = trace "x" (1 :: Int)


Prelude> (id x) + (id x)
x
2
Prelude> (id x) + (id x)
2

()$ LOPXT XIBUƊT VQ EFTQJUF UIF BEEJUJPO PG JEFOUJUZ GVOD


UJPOT /PUJDF UIF TFDPOE UJNF XF SBO JU JU EJEOƊU FWBMVBUF ԧ BU
BMM 5IF WBMVF PG ԧ JT OPX IFME UIFSF JO NFNPSZ TP XIFOFWFS
ZPVS QSPHSBN DBMMT ԧ JU BMSFBEZ LOPXT UIF WBMVF
$)"15&3  /0/453*$5/&44 

*O HFOFSBM ()$ SFMJFT PO BO JOUVJUJPO BSPVOE OBNFT BOE


TIBSJOH UP NBLF QFSGPSNBODF NPSF QSFEJDUBCMF )PXFWFS
UIJT XPOƊU BMXBZT CFIBWF JO XBZT ZPV FYQFDU $POTJEFS UIF
DBTF PG B MJTU XJUI B TJOHMF DIBSBDUFSƒBOE B 4USJOH XJUI B TJO
HMF DIBSBDUFS 5IFZƊSF BDUVBMMZ UIF TBNF UIJOH CVU UIF XBZ
UIFZ HFU DPOTUSVDUFE JT OPU 5IJT QSPEVDFT EJƵFSFODFT JO UIF
PQQPSUVOJTUJD TUSJDUOFTT ()$ XJMM FOHBHF JO

Prelude> let a = Just ['a']


Prelude> :sprint a
a = Just "a"

Prelude> let a = Just "a"


Prelude> :sprint a
a = Just _

4P VI XIBU HJWFT 8FMM UIF EFBM JT UIBU UIF TUSJDUOFTT BOBMZ


TJT ESJWFO PQUJNJ[BUJPO ()$ QFSGPSNT IFSF JT MJNJUFE UP EBUB
DPOTUSVDUPST POMZ OP DPNQVUBUJPO #VU XIFSFƊT UIF GVODUJPO
ZPV BTL 8FMM JG XF UVSO PO PVS OJHIU WJTJPO HPHHMFTƒ

Prelude> let a = Just ['a']

returnIO
(: ((Just (: (C# 'a') ([])))
`cast` ...) ([]))
$)"15&3  /0/453*$5/&44 

Prelude> let a = Just "a"

returnIO
(: ((Just (unpackCString# "a"#))
`cast` ...) ([]))

5IF JTTVF JT UIBU B DBMM UP B QSJNJUJWF GVODUJPO JO GHC.Base


JOUFSQPTFT +VTU BOE B $4USJOH MJUFSBM 5IF SFBTPO TUSJOH MJUFSBMT
BSFOƊU BDUVBMMZ MJTUT PG DIBSBDUFST BU UJNF PG DPOTUSVDUJPO JT
NPTUMZ UP QSFTFOU PQUJNJ[BUJPO PQQPSUVOJUJFT TVDI BT XIFO
XF DPOWFSU TUSJOH MJUFSBMT JOUP #ZUF4USJOHT PS 5FYU WBMVFT .PSF
PO UIBU JO UIF OFYU DIBQUFS

8IBU TVCWFSUT PS QSFWFOUT TIBSJOH


4PNFUJNFT XF EPOƊU XBOU TIBSJOH 4PNFUJNFT XF XBOU UP
LOPX XIZ TIBSJOH EJEOƊU IBQQFO XIFO XF EJE XBOU JU 6O
EFSTUBOEJOH XIBU LJOET PG UIJOHT QSFWFOU TIBSJOH JT UIFSFGPSF
VTFGVM
*OMJOJOH FYQSFTTJPOT XIFSF UIFZ HFU VTFE QSFWFOUT TIBSJOH
CFDBVTF JU DSFBUFT JOEFQFOEFOU UIVOLT UIBU XJMM HFU DPNQVUFE
TFQBSBUFMZ *O UIJT FYBNQMF JOTUFBE PG EFDMBSJOH UIF WBMVF PG ԕ
UP FRVBM  XF NBLF JU B GVODUJPO

Prelude> let f :: a -> Int; f _ = trace "f" 1


Prelude> f 'a'
f
$)"15&3  /0/453*$5/&44 

1
Prelude> f 'a'
f
1

*O UIF OFYU FYBNQMFT ZPV DBO EJSFDUMZ DPNQBSF UIF EJG


GFSFODF CFUXFFO BTTJHOJOH B OBNF UP UIF WBMVF PG (2 + 2) WFSTVT
JOMJOJOH JU EJSFDUMZ 8IFO JUƊT OBNFE JU HFUT TIBSFE BOE OPU
SFFWBMVBUFE

Prelude> let a :: Int; a = trace "a" 2 + 2


Prelude> let b = (a + a)
Prelude> b
a
8
Prelude> b
8

)FSF XF TBX Ԑ PODF XIJDI NBLFT TFOTF BT XF FYQFDU UIF


SFTVMU UP HFU TIBSFE

Prelude> :{
Prelude| let c :: Int;
Prelude| c = (trace "a" 2 + 2) + (trace "a" 2 + 2)
Prelude| :}
Prelude> c
a
$)"15&3  /0/453*$5/&44 

a
8
Prelude> c
8

)FSF BO FYQSFTTJPO FRVJWBMFOU UP Ԑ EJEOƊU HFU TIBSFE CF


DBVTF UIF UXP PDDVSSFODFT PG UIF FYQSFTTJPO XFSFOƊU CPVOE
UP UIF TBNF OBNF 5IJT JT B USJWJBM FYBNQMF PG JOMJOJOH 5IJT
JMMVTUSBUFT UIF EJƵFSFODF JO IPX UIJOHT FWBMVBUF XIFO BO FY
QSFTTJPO JT CPVOE UP B OBNF WFSTVT XIFO JU HFUT SFQFBUFE WJB
JOMJOJOH JO BO FYQSFTTJPO
#FJOH B GVODUJPO XJUI FYQMJDJU OBNFE BSHVNFOUT BMTP QSF
WFOUT TIBSJOH )BTLFMM JT OPU GVMMZ MB[Z JU JT NFSFMZ OPOTUSJDU
TP JU JT OPU SFRVJSFE UP SFNFNCFS UIF SFTVMU PG FWFSZ GVOD
UJPO BQQMJDBUJPO GPS B HJWFO TFU PG BSHVNFOUT OPS XPVME JU CF
EFTJSBCMF HJWFO NFNPSZ DPOTUSBJOUT " EFNPOTUSBUJPO

Prelude> let f :: a -> Int; f = trace "f" const 1


Prelude> f 'a'
f
1
Prelude> f 'a'
1
Prelude> f 'b'
1
$)"15&3  /0/453*$5/&44 

5IF FYQMJDJU OBNFE BSHVNFOUT QBSU IFSF JT DSJUJDBM &UB


DPOUSBDUJPO JF XSJUJOH QPJOUGSFF DPEF UIVT ESPQQJOH UIF
OBNFE BSHVNFOUT
XJMM DIBOHF UIF TIBSJOH QSPQFSUJFT PG ZPVS
DPEF 5IJT XJMM CF FYQMBJOFE JO NPSF EFUBJM JO UIF OFYU DIBQUFS
5ZQFDMBTT DPOTUSBJOUT BMTP QSFWFOU TIBSJOH *G XF GPSHFU UP
BEE B DPODSFUF UZQF UP BO FBSMJFS FYBNQMF XF FWBMVBUF Ԑ UXJDF

Prelude> let blah = Just 1


Prelude> fmap ((+1) :: Int -> Int) blah
Just 2
Prelude> :sprint blah
blah = _
Prelude> :t blah
blah :: Num a => Maybe a

Prelude> let bl = Just 1


Prelude> :t bl
bl :: Num a => Maybe a
Prelude> :sprint bl
bl = _
Prelude> fmap (+1) bl
Just 2

Prelude> let fm = fmap (+1) bl


Prelude> :t fm
fm :: Num b => Maybe b
Prelude> :sprint fm
$)"15&3  /0/453*$5/&44 

fm = _
Prelude> fm
Just 2
Prelude> :sprint fm
fm = _

Prelude> let fm' = fmap ((+1) :: Int -> Int) bla


Prelude> fm'
Just eval'd 1
2
Prelude> :sprint fm'
fm' = Just 2

"HBJO UIBUƊT CFDBVTF UZQFDMBTT DPOTUSBJOUT BSF B GVODUJPO


JO $PSF 5IFZ BSF BXBJUJOH BQQMJDBUJPO UP TPNFUIJOH UIBU XJMM
NBLF UIFN CFDPNF DPODSFUF UZQFT 8FƊSF HPJOH UP HP JOUP B
CJU NPSF EFUBJM PO UIJT JO UIF OFYU TFDUJPO
*NQMJDJU QBSBNFUFST BSF JNQMFNFOUFE TJNJMBSMZ UP UZQF
DMBTT DPOTUSBJOUT BOE IBWF UIF TBNF FƵFDU PO TIBSJOH 4IBSJOH
EPFTOƊU XPSL JO UIF QSFTFODF PG DPOTUSBJOUT UZQFDMBTTFT PS JN
QMJDJU QBSBNFUFST
CFDBVTF UZQFDMBTT DPOTUSBJOUT BOE JNQMJDJU
QBSBNFUFST EFDBZ JOUP GVODUJPO BSHVNFOUT XIFO UIF DPNQJMFS
TJNQMJƶFT UIF DPEF

Prelude> :set -XImplicitParams


Prelude> import Debug.Trace
Prelude> :{
$)"15&3  /0/453*$5/&44 

Prelude Debug.Trace| let add :: (?x :: Int) => Int


Prelude Debug.Trace| add = trace "add" 1 + ?x
Prelude Debug.Trace| :}
Prelude> let ?x = 1 in add
add
2
Prelude> let ?x = 1 in add
add
2

8F XPOƊU UBML BCPVU JNQMJDJU QBSBNFUFST UPP NVDI NPSF BT


XF EPOƊU UIJOL UIFZƊSF B HPPE JEFB GPS HFOFSBM VTF *O NPTU DBTFT
XIFSF ZPV CFMJFWF ZPV XBOU JNQMJDJU QBSBNFUFST NPSF MJLFMZ
ZPV XBOU 3FBEFS 3FBEFS5 PS B QMBJO PME GVODUJPO BSHVNFOU

8IZ QPMZNPSQIJD WBMVFT OFWFS TFFN UP HFU


GPSDFE
"T XFƊWF TBJE ()$ FOHBHFT JO PQQPSUVOJTUJD TUSJDUOFTT XIFO JU
DBO EP TP TBGFMZ XJUIPVU NBLJOH BO PUIFSXJTF WBMJE FYQSFTTJPO
SFTVMU JO CPUUPN 5IJT JT POF PG UIF UIJOHT UIBU DPOGPVOET UIF
VTF PG sprint UP PCTFSWF FWBMVBUJPO JO ()$J ƈ ()$ XJMM PǒFO
CF PQQPSUVOJTUJDBMMZ TUSJDU XJUI EBUB DPOTUSVDUPST JG JU LOPXT
UIF DPOUFOUT EFƶOJUFMZ DBOƊU CF B CPUUPN TVDI BT XIFO UIFZƊSF
B MJUFSBM WBMVF *U HFUT NPSF DPNQMJDBUFE XIFO XF DPOTJEFS
$)"15&3  /0/453*$5/&44 

UIBU VOEFS UIF IPPE UZQFDMBTT DPOTUSBJOUT BSF TJNQMJƶFE JOUP


BEEJUJPOBM BSHVNFOUT
3FVTJOH B TJNJMBS FYBNQMF GSPN FBSMJFS XF XJMM ƶSTU PCTFSWF
UIJT JO BDUJPO UIFO XFƊMM UBML BCPVU XIZ JU IBQQFOT

Prelude> let blah = Just (trace "eval'd 1" 1)


Prelude> :sprint blah
blah = _
Prelude> :t blah
blah :: Num a => Maybe a
Prelude> fmap (+1) blah
Just eval'd 1
2
Prelude> fmap (+1) blah
Just eval'd 1
2
Prelude> :sprint blah
blah = _

4P XF IBWF BU MFBTU TPNF FWJEFODF UIBU XFƊSF SFFWBMVBUJOH


%PFT JU DIBOHF XIFO JUƊT DPODSFUF

Prelude> let blah = Just (trace "eval'd 1" (1 :: Int))


Prelude> :sprint blah
blah = Just _
$)"15&3  /0/453*$5/&44 

5IF *OU WBMVF CFJOH PCTDVSFE CZ trace QSFWFOUFE PQQPS


UVOJTUJD FWBMVBUJPO UIFSF )PXFWFS FMJEJOH UIF Num a => a JO
GBWPS PG B DPODSFUF UZQF EPFT CSJOH TIBSJOH CBDL

Prelude> fmap (+1) blah


Just eval'd 1
2
Prelude> fmap (+1) blah
Just 2

/PX PVS USBDF HFUT FNJUUFE POMZ PODF 5IF JEFB IFSF JT UIBU
BǒFS UIF UZQFDMBTT DPOTUSBJOUT HFU TJNQMJƶFE UP UIF VOEFSMZJOH
()$ $PSF MBOHVBHF UIFZƊSF SFBMMZ GVODUJPO BSHVNFOUT
*U EPFTOƊU NBUUFS JG ZPV VTF B GVODUJPO UIBU BDDFQUT B DPODSFUF
UZQF BOE GPSDFT UIF Num a => a JUƊMM SFEP UIF XPSL PO FBDI
FWBMVBUJPO CFDBVTF PG UIF UZQFDMBTT DPOTUSBJOU 'PS FYBNQMF

Prelude> fmap ((+1) :: Int -> Int) blah


Just 2
Prelude> :sprint blah
blah = _
Prelude> :t blah
blah :: Num a => Maybe a

Prelude> let bl = Just 1


Prelude> :t bl
bl :: Num a => Maybe a
$)"15&3  /0/453*$5/&44 

Prelude> :sprint bl
bl = _
Prelude> fmap (+1) bl
Just 2
Prelude> let fm = fmap (+1) bl
Prelude> :t fm
fm :: Num b => Maybe b
Prelude> :sprint fm
fm = _
Prelude> fm
Just 2
Prelude> :sprint fm
fm = _

Prelude> let fm' = fmap ((+1) :: Int -> Int) blah


Prelude> fm'
Just eval'd 1
2
Prelude> :sprint fm'
fm' = Just 2

4P XIBUƊT UIF EFBM IFSF XJUI UIF UZQFDMBTT DPOTUSBJOUT *UƊT BT


JG Num a => a XFSF SFBMMZ Num a -> a *O $PSF UIFZ BSF 5IF POMZ
XBZ UP BQQMZ UIBU GVODUJPO BSHVNFOU JT UP SFBDI BO FYQSFTTJPO
UIBU QSPWJEFT B DPODSFUF UZQF TBUJTGZJOH UIF DPOTUSBJOU )FSFƊT
B EFNPOTUSBUJPO PG UIF EJƵFSFODF JO CFIBWJPS VTJOH WBMVFT
$)"15&3  /0/453*$5/&44 

Prelude> let poly = 1


Prelude> let conc = poly :: Int
Prelude> :sprint poly
poly = _
Prelude> :sprint conc
conc = _
Prelude> poly
1
Prelude> conc
1
Prelude> :sprint poly
poly = _
Prelude> :sprint conc
conc = 1

Num a => a JT B GVODUJPO BXBJUJOH BO BSHVNFOU XIJMF *OU JT


OPU #FIPME UIF $PSF

module Blah where

a :: Num a => a
a = 1

concrete :: Int
concrete = 1

Prelude> :l code/blah.hs
$)"15&3  /0/453*$5/&44 

[1 of 1] Compiling Blah

==================== Tidy Core ====================


Result size of Tidy Core =
{terms: 9, types: 9, coercions: 0}

concrete
concrete = I# 1

a
a =
\ @ a1_aRN $dNum_aRP ->
fromInteger $dNum_aRP (__integer 1)

%P ZPV TFF IPX Ԑ IBT B MBNCEB *O PSEFS UP LOPX XIBU


JOTUBODF PG UIF UZQFDMBTT UP EFQMPZ BU BOZ HJWFO UJNF UIF UZQF
IBT UP CF DPODSFUF "T XFƊWF TFFO UZQFT DBO CFDPNF DPODSFUF
UISPVHI BTTJHONFOU PS UZQF EFGBVMUJOH 8IJDIFWFS XBZ JU
CFDPNFT DPODSFUF UIF SFTVMU JT UIF TBNF PODF UIF DPODSFUF
UZQF JT LOPXO UIF UZQFDMBTT DPOTUSBJOU GVODUJPO HFUT BQQMJFE
UP UIF UZQFDMBTT JOTUBODF GPS UIBU UZQF *G ZPV EPOƊU EFDMBSF UIF
DPODSFUF UZQF JU XJMM IBWF UP SFFWBMVBUF UIJT GVODUJPO FWFSZ
UJNF CFDBVTF JU DBOƊU LOPX UIBU UIF UZQF EJEOƊU DIBOHF TPNF
XIFSF BMPOH UIF XBZ 4P CFDBVTF JU SFNBJOT B GVODUJPO BOE
VOBQQMJFE GVODUJPOT BSF OPU TIBSFBCMF WBMVFT QPMZNPSQIJD
FYQSFTTJPOT DBOƊU CF TIBSFE
$)"15&3  /0/453*$5/&44 

.PTUMZ UIF CFIBWJPS EPFTOƊU DIBOHF XIFO JU JOWPMWFT WBM


VFT EFƶOFE JO UFSNT PG GVODUJPOT CVU JG ZPV GPSHFU UIF UZQF
DPODSFUJPO JUƊMM TUBZ _ BOE ZPVƊMM CF DPOGVTFE BOE VQTFU 0C
TFSWF

Prelude> let blah :: Int -> Int; blah x = x + 1


Prelude> let woot = blah 1
Prelude> :sprint blah
blah = _
Prelude> :sprint woot
woot = _
Prelude> woot
2
Prelude> :sprint woot
woot = 2

7BMVFT PG B DPODSFUF DPOTUBOU UZQF DBO CF TIBSFE PODF


FWBMVBUFE 1PMZNPSQIJD WBMVFT NBZ CF FWBMVBUFE PODF CVU TUJMM
OPU TIBSFE CFDBVTF VOEFSOFBUI UIFZ DPOUJOVF UP CF GVODUJPOT
BXBJUJOH BQQMJDBUJPO

1SFWFOUJOH TIBSJOH PO QVSQPTF


8IFO EP XF XBOU UP QSFWFOU TIBSJOH 8IFO XF EPOƊU XBOU
B MBSHF EBUVN IBOHJOH PVU JO NFNPSZ UIBU XBT DBMDVMBUFE UP
QSPWJEF B NVDI TNBMMFS BOTXFS 'JSTU BO FYBNQMF UIBU EFNPO
TUSBUFT TIBSJOH
$)"15&3  /0/453*$5/&44 

Prelude> import Debug.Trace


Prelude> let f x = x + x
Prelude> f (trace "hi" 2)
hi
4

8F TFF ƌIJƍ PODF CFDBVTF ԧ HPU FWBMVBUFE PODF *O UIF OFYU


FYBNQMF ԧ HFUT FWBMVBUFE UXJDF

Prelude> let f x = (x ()) + (x ())


Prelude> f (\_ -> trace "hi" 2)
hi
hi
4

6TJOH VOJU () BT BSHVNFOUT UP ԧ UVSOFE ԧ JOUP B WFSZ USJWJBM


XFJSEMPPLJOH GVODUJPO XIJDI JT XIZ UIF WBMVF PG ԧ DBO OP
MPOHFS CF TIBSFE *U EPFTOƊU NBUUFS NVDI TJODF UIBU ƌGVODUJPOƍ
ԧ EPFTOƊU SFBMMZ EP BOZUIJOH
0, UIBU XBT XFJSE NBZCF JUƊMM CF FBTJFS UP TFF JG XF VTF
TPNF NPSF USBEJUJPOBMTFFNJOH BSHVNFOU UP ԧ

Prelude> let f x = (x 2) + (x 10)


Prelude> f (\x -> trace "hi" (x + 1))
hi
hi
14
$)"15&3  /0/453*$5/&44 

6TJOH B MBNCEB UIBU NFOUJPOT UIF BSHVNFOU JO TPNF GBTI


JPO EJTBCMFT TIBSJOH

Prelude> let g = \_ -> trace "hi" 2


Prelude> f g
hi
hi
4

)PXFWFS UIJT XPSLFE JO QBSU CFDBVTF UIF GVODUJPO QBTTFE


UP ԕ IBE UIF BSHVNFOU BT QBSU PG UIF EFDMBSBUJPO FWFO UIPVHI
JU VTFE VOEFSTDPSF UP JHOPSF JU /PUJDF XIBU IBQQFOT JG XF
NBLF JU QPJOUGSFF

Prelude> let g = const (trace "hi" 2)


Prelude> f g
hi
4

8FƊSF HPJOH UP HFU JOUP B MJUUMF NPSF EFUBJM BCPVU UIJT EJT
UJODUJPO JO UIF OFYU DIBQUFS CVU UIF JEFB IFSF JT UIBU GVODUJPOT
BSFOƊU TIBSFE XIFO UIFSF BSF OBNFE BSHVNFOUT CVU BSF XIFO
UIF BSHVNFOUT BSF FMJEFE BT JO QPJOUGSFF 4P POF XBZ UP QSF
WFOU TIBSJOH JT BEEJOH OBNFE BSHVNFOUT
$)"15&3  /0/453*$5/&44 

'PSDJOH TIBSJOH
:PV DBO GPSDF TIBSJOH CZ HJWJOH ZPVS FYQSFTTJPO B OBNF 5IF
NPTU DPNNPO XBZ PG EPJOH UIJT JT XJUI MFU

-- calculates 1 + 1 twice
(1 + 1) * (1 + 1)

-- shares 1 + 1 result under 'x'


let x = 1 + 1
in x * x

8JUI UIBU JO NJOE JG ZPV UBLF B MPPL BU UIF GPSFWFS GVODUJPO


JO $POUSPM.POBE ZPV NJHIU TFF TPNFUIJOH B MJUUMF NZTUFSJPVT
MPPLJOH

forever :: (Monad m) => m a -> m b


forever a = let a' = a >> a' in a'

8IZ UIF MFU FYQSFTTJPO 8FMM XF XBOU TIBSJOH IFSF TP UIBU


SVOOJOH B NPOBEJD BDUJPO JOEFƶOJUFMZ EPFTOƊU MFBL NFNPSZ
5IF TIBSJOH IFSF DBVTFT ()$ UP PWFSXSJUF UIF UIVOL BT JU SVOT
FBDI TUFQ JO UIF FWBMVBUJPO XIJDI JT RVJUF IBOEZ 0UIFSXJTF
JU XPVME LFFQ DPOTUSVDUJOH OFX UIVOLT JOEFƶOJUFMZ BOE UIBU
XPVME CF WFSZ VOGPSUVOBUF
$)"15&3  /0/453*$5/&44 

 3FGVUBCMF BOE JSSFGVUBCMF QBUUFSOT


8IFO XFƊSF UBMLJOH BCPVU QBUUFSO NBUDIJOH JUƊT JNQPSUBOU UP
CF BXBSF UIBU UIFSF BSF SFGVUBCMF BOE JSSFGVUBCMF QBUUFSOT "O
JSSFGVUBCMF QBUUFSO JT POF XIJDI XJMM OFWFS GBJM UP NBUDI "
SFGVUBCMF QBUUFSO JT POF XIJDI IBT QPUFOUJBM GBJMVSFT 0ǒFO
UIF QSPCMFN JT POF PG TQFDJƶDJUZ

refutable :: Bool -> Bool


refutable True = False
refutable False = True

irrefutable :: Bool -> Bool


irrefutable x = not x

oneOfEach :: Bool -> Bool


oneOfEach True = False
oneOfEach _ = True

3FNFNCFS UIF QBUUFSO JT SFGVUBCMF PS OPU OPU UIF GVODUJPO


JUTFMG 5IF GVODUJPO refutable JT SFGVUBCMF CFDBVTF FBDI DBTF JT
SFGVUBCMF FBDI DBTF DPVME CF HJWFO BO JOQVU UIBU GBJMT UP NBUDI
*O DPOUSBTU irrefutable IBT BO JSSFGVUBCMF QBUUFSO UIBU JT JUT
QBUUFSO EPFTOƊU SFMZ PO NBUDIJOH XJUI B TQFDJƶD WBMVF
*O UIF DBTF PG oneOfEach UIF ƶSTU QBUUFSO JT SFGVUBCMF CFDBVTF
JU QBUUFSO NBUDIFT PO UIF True EBUB DPOTUSVDUPS irrefutable
$)"15&3  /0/453*$5/&44 

BOE UIF TFDPOE NBUDI PG oneOfEach BSF JSSFGVUBCMF CFDBVTF UIFZ


EPOƊU OFFE UP ƌMPPL JOTJEFƍ UIF EBUB UIFZ BSF BQQMJFE UP
5IBU TBJE UIF TFDPOE QBUUFSO NBUDI PG oneOfEach CFJOH JS
SFGVUBCMF JTOƊU UFSSJCMZ TFNBOUJDBMMZ NFBOJOHGVM BT )BTLFMM XJMM
IBWF UP JOTQFDU UIF EBUB UP TFF JG JU NBUDIFT UIF ƶSTU DBTF BOZ
XBZ
5IF irrefutable GVODUJPO XPSLT GPS BOZ JOIBCJUBOU BMM UXP
PG UIFN
PG #PPM CFDBVTF JU EPFTOƊU TQFDJGZ XIJDI #PPM WBMVF JO
UIF QBUUFSO UP NBUDI :PV DPVME UIJOL PG BO JSSFGVUBCMF QBUUFSO
BT POF XIJDI XJMM OFWFS GBJM UP NBUDI *G BO JSSFGVUBCMF QBUUFSO
GPS B QBSUJDVMBS WBMVF DPNFT CFGPSF B SFGVUBCMF QBUUFSO UIF
SFGVUBCMF QBUUFSO XJMM OFWFS HFU JOWPLFE
5IJT MJUUMF GVODUJPO BQQFBSFE JO BO FBSMJFS DIBQUFS CVU XFƊMM
CSJOH JU CBDL GPS B RVJDL BOE FBTZ EFNPOTUSBUJPO

isItTwo :: Integer -> Bool


isItTwo 2 = True
isItTwo _ = False

*O UIF DBTF PG #PPM UIF PSEFS PG NBUDIJOH 5SVF BOE 'BMTF


TQFDJƶDBMMZ EPFTOƊU NBUUFS CVU JO DBTFT MJLF isItTwo XIFSF POF
DBTF JT TQFDJƶD BOE UIF PUIFS JT B DBUDIBMM PUIFSXJTF DBTF UIF
PSEFSJOH XJMM DFSUBJOMZ NBUUFS :PV DBO SFPSEFS UIF FYQSFTTJPOT
PG isItTwo UP TFF XIBU IBQQFOT BMUIPVHI JUƊT QSPCBCMZ DMFBS
$)"15&3  /0/453*$5/&44 

-B[Z QBUUFSOT
-B[Z QBUUFSOT BSF BMTP JSSFGVUBCMF

strictPattern :: (a, b) -> String


strictPattern (a,b) = const "Cousin It" a

lazyPattern :: (a, b) -> String


lazyPattern ~(a,b) = const "Cousin It" a

5IF UJMEF JT IPX POF NBLFT B QBUUFSO NBUDI MB[Z " DBWFBU
JT UIBU TJODF JU NBLFT UIF QBUUFSO JSSFGVUBCMF ZPV DBOƊU VTF
JU UP EJTDSJNJOBUF DBTFT PG B TVN ƈ JUƊT VTFGVM GPS VOQBDLJOH
QSPEVDUT UIBU NJHIU OPU HFU VTFE

Prelude> strictPattern undefined


*** Exception: Prelude.undefined

Prelude> lazyPattern undefined


"Cousin It"

"OE BT XF TFF IFSF JO UIF MB[Z QBUUFSO WFSTJPO TJODF const


EJEOƊU BDUVBMMZ OFFE Ԑ GSPN UIF UVQMF XF OFWFS GPSDFE UIF
CPUUPN 5IF EFGBVMU CFIBWJPS JT UP KVTU HP BIFBE BOE GPSDF
JU CFGPSF FWBMVBUJOH UIF GVODUJPO CPEZ NPTUMZ GPS NPSF QSF
EJDUBCMF NFNPSZ VTBHF BOE QFSGPSNBODF
$)"15&3  /0/453*$5/&44 

 #BOHQBUUFSOT
4PNFUJNFT XF XBOU UP FWBMVBUF BO BSHVNFOU UP B GVODUJPO
XIFUIFS XF VTF JU PS OPU 8F DBO EP UIJT XJUI seq BT JO UIF
GPMMPXJOH FYBNQMF

{-# LANGUAGE BangPatterns #-}

module ManualBang where

doesntEval :: Bool -> Int


doesntEval b = 1

manualSeq :: Bool -> Int


manualSeq b = b `seq` 1

0S XF DBO BMTP EP JU XJUI B CBOHQBUUFSO PO ԑ ƈ OPUF UIF


FYDMBNBUJPO QPJOU

banging :: Bool -> Int


banging !b = 1

-FUƊT MPPL BU UIF $PSF GPS UIPTF UISFF


$)"15&3  /0/453*$5/&44 

doesntEval
doesntEval =
\ _ -> I# 1#

manualSeq
manualSeq =
\ b_a1ia ->
case b_a1ia of _
{ __DEFAULT -> I# 1# }

banging
banging =
\ b_a1ib ->
case b_a1ib of _
{ __DEFAULT -> I# 1# }

*G ZPV USZ QBTTJOH CPUUPN UP FBDI GVODUJPO ZPVƊMM ƶOE UIBU


manualSeq BOE CBOHJOH BSF GPSDJOH UIFJS BSHVNFOU EFTQJUF OPU
VTJOH JU GPS BOZUIJOH 3FNFNCFS UIBU GPSDJOH TPNFUIJOH JT
FYQSFTTFE JO DPSF BT B DBTF FYQSFTTJPO BOE UIBU DBTF FWBMVBUFT
VQ UP XFBL IFBE OPSNBM GPSN JO $PSF

#BOH QBUUFSOT JO EBUB


8IFO XF FWBMVBUF UIF PVUFS EBUB DPOTUSVDUPS PG B EBUB UZQF
BU UJNFT XFƊE BMTP MJLF UP FWBMVBUF UIF DPOUFOUT UP XFBL IFBE
$)"15&3  /0/453*$5/&44 

OPSNBM GPSN KVTU MJLF XJUI GVODUJPOT


" TJNQMF XBZ UP TFF UIF EJƵFSFODF CFUXFFO TUSJDU BOE OPO
TUSJDU DPOTUSVDUPS BSHVNFOUT JT IPX UIFZ CFIBWF XIFO UIFZ
BSF VOEFƶOFE -FUƊT MPPL BU BO FYBNQMF OPUF UIF FYDMBNBUJPO
NBSL


data Foo = Foo Int !Int

first (Foo x _) = x
second (Foo _ y) = y

4JODF UIF OPOTUSJDU BSHVNFOU JTOƊU FWBMVBUFE CZ second QBTT


JOH JO VOEFƶOFE EPFTOƊU DBVTF B QSPCMFN

> second (Foo undefined 1)


1

#VU UIF TUSJDU BSHVNFOU DBOƊU CF VOEFƶOFE FWFO JG XF EPOƊU


VTF UIF WBMVF

> first (Foo 1 undefined)


*** Exception: Prelude.undefined

:PV DPVME EP UIJT NBOVBMMZ XJUI seq CVU JUƊT B MJUUMF UFEJPVT
)FSFƊT BOPUIFS FYBNQMF XJUI UXP FRVJWBMFOU EBUBUZQFT POF
PG UIFN XJUI TUSJDUOFTT BOOPUBUJPOT PO UIF DPOUFOUT BOE POF
XJUIPVU
$)"15&3  /0/453*$5/&44 

{-# LANGUAGE BangPatterns #-}

module ManualBang where

data DoesntForce =
TisLazy Int String

gibString :: DoesntForce -> String


gibString (TisLazy _ s) = s

-- note the exclamation marks again


data BangBang =
SheShotMeDown !Int !String

gimmeString :: BangBang -> String


gimmeString (SheShotMeDown _ s) = s

5IFO UFTUJOH UIPTF JO ()$J

Prelude> let x = TisLazy undefined "blah"


Prelude> gibString x
"blah"
Prelude> let x = SheShotMeDown undefined "blah"
Prelude> gimmeString x
"*** Exception: Prelude.undefined
$)"15&3  /0/453*$5/&44 

5IF JEFB IFSF JT UIBU JO TPNF DBTFT JUƊT DIFBQFS UP KVTU DPN
QVUF TPNFUIJOH UIBO UP DPOTUSVDU B UIVOL BOE UIFO FWBMV
BUF JU MBUFS 5IJT DBTF JT QBSUJDVMBSMZ DPNNPO JO OVNFSJDT
DPEF XIFSF ZPV IBWF B MPU PG *OU BOE %PVCMF WBMVFT SVOOJOH
BSPVOE XIJDI BSF JOEJWJEVBMMZ DIFBQ UP DPOKVSF *G UIF WBMVFT
BSF CPUI DIFBQ UP DPNQVUF BOE TNBMM UIFO ZPV NBZ BT XFMM
NBLF UIFN TUSJDU VOMFTT ZPVƊSF USZJOH UP EBODF BSPVOE CPU
UPNT 5ZQFT XJUI VOEFSMZJOH QSJNJUJWF SFQSFTFOUBUJPOT *OU
BOE %PVCMF NPTU BTTVSFEMZ RVBMJGZ BT TNBMM
" HPPE SVMF UP GPMMPX JT MB[Z JO UIF TQJOF TUSJDU JO UIF MFBWFT
4PNFUJNFT B ƌMFBLƍ JTOƊU SFBMMZ B MFBL CVU UFNQPSBSJMZ FYDFT
TJWF NFNPSZ UIBU TVCTJEFT CFDBVTF ZPV NBEF    UJOZ
WBMVFT JOUP MFTTUJOZ UIVOLT XIFO ZPV DPVMEƊWF KVTU DPNQVUFE
UIFN BT ZPVS BMHPSJUIN QSPHSFTTFE

 4USJDU BOE 4USJDU%BUB


*G ZPVƊSF VTJOH ()$  PS OFXFS ZPV DBO BWBJM ZPVSTFMG PG
UIF 4USJDU BOE 4USJDU%BUB QSBHNBT 5IF LFZ UIJOH UP SFBMJ[F JT
4USJDU4USJDU%BUB BSF KVTU MFUUJOH ZPV BWPJE QVUUJOH JO QFSWBTJWF
VTFT PG seq BOE CBOH QBUUFSOT ZPVSTFMG 5IFZ EPOƊU BEE BOZ
UIJOH UP UIF TFNBOUJDT PG UIF MBOHVBHF "DDPSEJOHMZ JU XPOƊU
TVEEFOMZ NBLF MB[Z EBUB TUSVDUVSFT EFƶOFE FMTFXIFSF CFIBWF
EJƵFSFOUMZ BMUIPVHI JU EPFT NBLF GVODUJPOT EFƶOFE JO UIBU
NPEVMF QSPDFTTJOH MB[Z EBUB TUSVDUVSFT CFIBWF EJƵFSFOUMZ
$)"15&3  /0/453*$5/&44 

-FUƊT QMBZ XJUI UIBU JG ZPV BMSFBEZ IBWF ()$  PS OFXFS
JG OPU UIJT DPEF XPOƊU XPSL


{-# LANGUAGE Strict #-}

module StrictTest where

blah x = 1

main = print (blah undefined)

5IF BCPWF XJMM CPUUPN PVU CFDBVTF blah JT EFƶOFE VOEFS


UIF NPEVMF XJUI UIF 4USJDU QSBHNB BOE XJMM HFU USBOTMBUFE JOUP
UIF GPMMPXJOH

blah x = x `seq` 1

-- or with bang patterns


blah !x = 1

4P UIF 4USJDU BOE 4USJDU%BUB QSBHNBT BSF B NFBOT PG BWPJE


JOH OPJTF XIFO FWFSZUIJOH PS BMNPTU FWFSZUIJOH JO B NPEVMF
JT TVQQPTFE UP CF TUSJDU :PV DBO VTF UIF UJMEF GPS JSSFGVUBCMF
QBUUFSOT UP SFDPWFS MB[JOFTT PO B DBTF CZ DBTF CBTJT
$)"15&3  /0/453*$5/&44 

{-# LANGUAGE Strict #-}

module LazyInHostileTerritory where

willForce x = 1
willNotForce ~x = 1

"ENJUUFEMZ UIFTF BSF HMPSJƶFE SFOBNFT PG const CVU JU EPFTOƊU


NBUUFS GPS UIF QVSQPTFT PG EFNPOTUSBUJOH XIBU IBQQFOT )FSFƊT
XIBU XFƊMM TFF JO ()$J XIFO XF QBTT UIFN CPUUPN

Prelude> willForce undefined


*** Exception: Prelude.undefined
Prelude> willNotForce undefined
1

4P FWFO XIFO ZPVƊSF VTJOH UIF 4USJDU QSBHNB ZPV DBO TF
MFDUJWFMZ SFDPWFS MB[JOFTT XIFO EFTJSFE

 "EEJOH TUSJDUOFTT


/PX XF TIBMM FYBNJOF IPX BQQMZJOH TUSJDUOFTT UP B EBUBUZQF
BOE PQFSBUJPOT XFƊSF BMSFBEZ GBNJMJBS XJUI DBO DIBOHF IPX
UIFZ CFIBWF JO UIF QSFTFODF PG CPUUPN UISPVHI UIF MJTU UZQF
5IJT JT JOUFOEFE UP CF NPTUMZ EFNPOTUSBUJWF SBUIFS UIBO B
QSBDUJDBM FYBNQMF
$)"15&3  /0/453*$5/&44 

module StrictTest1 where

data List a =
Nil
| Cons a (List a) deriving Show

sTake :: Int -> List a -> List a


sTake n _
| n <= 0 = Nil
sTake n Nil = Nil
sTake n (Cons x xs) = (Cons x (sTake (n-1) xs))

twoEls = Cons 1 (Cons undefined Nil)


oneEl = sTake 1 twoEls

5IF OBNF PG UIF NPEVMF IFSF JT B CJU PG B NJTOPNFS List


IFSF JT MB[Z KVTU MJLF UIF CVJMUJO [a] JO UIF )BTLFMM QSFMVEF
0VS take EFSJWBUJWF OBNFE sTake JT MB[Z UPP
/PX MFUƊT MPBE VQ UIJT DPEF JO PVS 3&1- BOE UFTU JU PVU

Prelude> twoEls
Cons 1 (Cons *** Exception: Prelude.undefined

Prelude> oneEl
Cons 1 Nil
$)"15&3  /0/453*$5/&44 

/PX MFUƊT CFHJO FYQFSJNFOUJOH XJUI XIBU DIBOHFT JO PVS


DPEFƊT CFIBWJPS BT XF BEE TUSJDUOFTT UP EJƵFSFOU QBSUT PG PVS
QSPHSBN
'JSTU XFƊSF HPJOH UP BEE BangPatterns TP UIBU XF IBWF B TZO
UBDUJDBMMZ DPOWFOJFOU XBZ UP EFOPUF XIFO BOE XIFSF XF XBOU
TUSJDUOFTT

module StrictTest2 where

data List a =
Nil
| Cons !a (List a) deriving Show

sTake :: Int -> List a -> List a


sTake n _
| n <= 0 = Nil
sTake n Nil = Nil
sTake n (Cons x xs) = (Cons x (sTake (n-1) xs))

twoEls = Cons 1 (Cons undefined Nil)


oneEl = sTake 1 twoEls

/PUJOH UIF QMBDFNFOU PG UIF FYDMBNBUJPO NBSLT EFOPUJOH


TUSJDUOFTT MFUƊT SVO JU JO ()$J BOE TFF JG JU EPFT XIBU XF XBOU

Prelude> twoEls
$)"15&3  /0/453*$5/&44 

Cons 1 *** Exception: Prelude.undefined


Prelude> oneEl
Cons 1 Nil

{-# LANGUAGE BangPatterns #-}

module StrictTest3 where

data List a =
Nil
| Cons !a (List a) deriving Show

sTake :: Int -> List a -> List a


sTake n _
| n <= 0 = Nil
sTake n Nil = Nil
sTake n (Cons x !xs) = (Cons x (sTake (n-1) xs))

twoEls = Cons 1 (Cons undefined Nil)


oneEl = sTake 1 twoEls

threeElements = Cons 2 twoEls


oneElT = sTake 1 threeElements

8F BEEFE TUSJDUOFTT UP UIF ԧԢ TP UIBU sTake JT HPJOH UP GPSDF


NPSF PG UIF MJTU -FUƊT TFF XIBU IBQQFOT
$)"15&3  /0/453*$5/&44 

Prelude> twoEls
Cons 1 *** Exception: Prelude.undefined

Prelude> oneEl
*** Exception: Prelude.undefined

Prelude> threeElements
Cons 2 (Cons 1 *** Exception: Prelude.undefined

Prelude> oneElT
Cons 2 Nil

-FUƊT BEE NPSF TUSJDUOFTT


$)"15&3  /0/453*$5/&44 

module StrictTest4 where

data List a =
Nil
| Cons !a !(List a) deriving Show

sTake :: Int -> List a -> List a


sTake n _
| n <= 0 = Nil
sTake n Nil = Nil
sTake n (Cons x xs) = (Cons x (sTake (n-1) xs))

twoEls = Cons 1 (Cons undefined Nil)


oneEl = sTake 1 twoEls

"OE SVO JU BHBJO

Prelude> twoEls
*** Exception: Prelude.undefined

Prelude> oneEl
*** Exception: Prelude.undefined

4P XIBUƊT UIF VQTIPU PG PVS FYQFSJNFOUT XJUI BEEJOH TUSJDU


OFTT IFSF
$)"15&3  /0/453*$5/&44 

/ $POT T5BLF
 $POT B -JTU B
$POT Y YT
 $POT B -JTU B
$POT Y YT
 $POT B -JTU B
$POT Y YT
 $POT B  -JTU B
$POT Y YT

5IFO UIF SFTVMUT UIFNTFMWFT

/ UXP&MT POF&M
 $POT  $POT $POT  /JM
 $POT  $POT  /JM
 $POT 


:PV DBO TFF DMFBSMZ XIBU BEEJOH TUSJDUOFTT JO EJƵFSFOU QMBDFT


EPFT UP PVS FWBMVBUJPO JO UFSNT PG CPUUPN

 $IBQUFS &YFSDJTFT


4USJDU -JTU
5SZ QVU[JOH BSPVOE XJUI UIF GPMMPXJOH MJTU UZQF BOE DPNQBSF
XIBU JU EPFT XJUI UIF CBOHQBUUFSOFE MJTU WBSJBOUT XF FYQFSJ
NFOUFE XJUI FBSMJFS
$)"15&3  /0/453*$5/&44 

{-# LANGUAGE Strict #-}

module StrictList where

data List a =
Nil |
Cons a (List a)
deriving (Show)

take' n _ | n <= 0 = Nil


take' _ Nil = Nil
take' n (Cons x xs) = (Cons x (take' (n-1) xs))

map' _ Nil = Nil


map' f (Cons x xs) = (Cons (f x) (map' f xs))

repeat' x = xs where xs = (Cons x xs)

main = do
print $ take' 10 $ map' (+1) (repeat' 1)

8IBU XJMM TQSJOU PVUQVU


8F TIPX ZPV B EFƶOJUJPO PS NVMUJQMF EFƶOJUJPOT ZPV EFUFS
NJOF XIBU :sprint XJMM PVUQVU XIFO QBTTFE UIF CJOEJOHT MJTUFE
JO ZPVS IFBE CFGPSF UFTUJOH JU
$)"15&3  /0/453*$5/&44 

 let x = 1

 let x = ['1']

 let x = [1]

 let x = 1 :: Int

 let f = \x -> x
let x = f 1

 let f :: Int -> Int; f = \x -> x


let x = f 1

8JMM QSJOUJOH UIJT FYQSFTTJPO SFTVMU JO CPUUPN


 snd (undefined, 1)

 let x = undefined
let y = x `seq` 1 in snd (x, y)

 length $ [1..5] ++ undefined

 length $ [1..5] ++ [undefined]

 const 1 undefined

 const 1 (undefined `seq` 1)

 const undefined 1
$)"15&3  /0/453*$5/&44 

.BLF UIF FYQSFTTJPO CPUUPN


6TJOH POMZ CBOH QBUUFSOT PS TFR NBLF UIF DPEF CPUUPN PVU
XIFO FYFDVUFE

 x = undefined
y = "blah"
main = do
print (snd (x, y))

 'PMMPXVQ SFTPVSDFT


 5IF *ODPNQMFUF (VJEF UP -B[Z &WBMVBUJPO JO )BTLFMM

)FJOSJDI "QGFMNVT
https://hackhands.com/guide-lazy-evaluation-haskell/

 $IBQUFS  #BTJD 1BSBMMFMJTN 5IF &WBM .POBE 1BSBMMFM


BOE $PODVSSFOU 1SPHSBNNJOH JO )BTLFMM 4JNPO .BSMPX
http://chimera.labs.oreilly.com/books/1230000000929/ch02.html

 -B[Z FWBMVBUJPO JMMVTUSBUFE GPS )BTLFMM EJWFST 5BLFOPCV


5BOJ

 4FRVFODF QPJOU
https://en.wikipedia.org/wiki/Sequence_point

 " /BUVSBM 4FNBOUJDT GPS -B[Z &WBMVBUJPO +PIO -BVODI


CVSZ
$)"15&3  /0/453*$5/&44 

 "O 0QFSBUJPOBM 4FNBOUJDT GPS 1BSBMMFM $BMMCZ/FFE $MFN


#BLFS'JODI %BWJE ,JOH +PO )BMM BOE 1IJM 5SJOEFS
$IBQUFS 

#BTJD MJCSBSJFT

#BE QSPHSBNNFST XPSSZ


BCPVU UIF DPEF (PPE
QSPHSBNNFST XPSSZ
BCPVU EBUB TUSVDUVSFT BOE
UIFJS SFMBUJPOTIJQT

-JOVT 5PSWBMET


$)"15&3  #"4*$ -*#3"3*&4 

 #BTJD MJCSBSJFT BOE EBUB TUSVDUVSFT


%BUB TUSVDUVSFT BSF LJOE PG JNQPSUBOU *OTPGBS BT DPNQVUFST
BSF GBTU UIFZ BSFOƊU HFUUJOH NVDI GBTUFS ƈ BU MFBTU UIF $16
JTOƊU 5IJT JT VTVBMMZ B MFBEJO GPS B QBSBMMFMJTNDPODVSSFODZ
TBMFT QJUDI #VU UIJT JTOƊU UIBU CPPL
5IF EBUB TUSVDUVSFT ZPV DIPPTF UP SFQSFTFOU ZPVS QSPCMFN
BƵFDU UIF TQFFE BOE NFNPSZ JOWPMWFE JO QSPDFTTJOH ZPVS EBUB
QFSIBQT UP B MBSHFS FYUFOU UIBO JT JNNFEJBUFMZ PCWJPVT "U UIF
MFWFM PG ZPVS QSPHSBN NBLJOH UIF SJHIU EFDJTJPO BCPVU IPX
UP SFQSFTFOU ZPVS EBUB JT UIF ƶSTU JNQPSUBOU TUFQ UP XSJUJOH
FƸDJFOU QSPHSBNT *O GBDU ZPVS DIPJDF PG EBUB TUSVDUVSF DBO
BƵFDU XIFUIFS JUƊT XPSUIXIJMF PS FWFO NBLFT TFOTF UP BUUFNQU
UP QBSBMMFMJ[F TPNFUIJOH
5IJT DIBQUFS JT IFSF UP IFMQ ZPV NBLF UIF EFDJTJPO PG UIF
PQUJNBM EBUB TUSVDUVSFT GPS ZPVS QSPHSBNT 8F DBOƊU QSFTDSJCF
POF PS UIF PUIFS PG TJNJMBS EBUB TUSVDUVSFT CFDBVTF IPX FG
GFDUJWF UIFZ BSF XJMM EFQFOE B MPU PO XIBU ZPVƊSF USZJOH UP
EP 4P PVS ƶSTU TUFQ XJMM CF UP HJWF ZPV UPPMT UP NFBTVSF GPS
ZPVSTFMG IPX EJƵFSFOU TUSVDUVSFT XJMM QFSGPSN JO ZPVS DPOUFYU
8FƊMM BMTP DPWFS TPNF PG UIF NJTUBLFT UIBU DBO DBVTF ZPVS
NFNPSZ VTBHF BOE UJNF UP FWBMVBUF UP FYQMPEF
5IJT DIBQUFS XJMM

Ƒ EFNPOTUSBUF IPX UP NFBTVSF UIF VTBHF PG UJNF BOE TQBDF


JO ZPVS QSPHSBNT
$)"15&3  #"4*$ -*#3"3*&4 

Ƒ PƵFS HVJEFMJOFT PO XIFO XFBL IFBE OPSNBM GPSN PS OPS


NBM GPSN BSF BQQSPQSJBUF XIFO CFODINBSLJOH DPEF

Ƒ EFƶOF DPOTUBOU BQQMJDBUJWF GPSNT BOE FYQMBJO BSHVNFOU


TBUVSBUJPO

Ƒ EFNPOTUSBUF BOE DSJUJDBMMZ FWBMVBUF XIFO UP VTF EJƵFSFOU


EBUB TUSVDUVSFT JO EJƵFSFOU DJSDVNTUBODFT

Ƒ TBDSJƶDF TPNF KBSHPO GPS UIF KBSHPO HPET

8FƊSF HPJOH UP LJDL UIJT DIBQUFS PƵ XJUI TPNF CFODINBSL


JOH

 #FODINBSLJOH XJUI $SJUFSJPO


*UƊT B DPNNPO FOPVHI UIJOH UP XBOU UP LOPX IPX GBTU PVS
DPEF JT *G ZPV DBOƊU CFODINBSL QSPQFSMZ UIFO ZPV DBOƊU LOPX
JG ZPV VTFE TJY NJDSPTFDPOET PS POMZ ƶWF BOE DBO POMZ BTL
ZPVSTFMG ƌ8FMM EP * GFFM MVDLZ ƍ
8FMM EP ZB QVOL
*G ZPVƊE SBUIFS OPU USVTU ZPVS QFSGPSNBODF UP HVFTTXPSL
UIF CFTU XBZ UP NFBTVSF QFSGPSNBODF JT UP TBNQMF NBOZ UJNFT
JO PSEFS UP FTUBCMJTI B DPOƶEFODF JOUFSWBM 'PSUVOBUFMZ UIBU
XPSL IBT BMSFBEZ CFFO EPOF GPS VT JO UIF XPOEFSGVM MJCSBSZ
DSJUFSJPO CZ #SZBO 0Ɗ4VMMJWBO

http://hackage.haskell.org/package/criterion
$)"15&3  #"4*$ -*#3"3*&4 

5IJT JT OPU UIF ƶSTU MJCSBSZ PG IJT XFƊWF NFOUJPOFE JO UIJT


CPPL .S 0Ɗ4VMMJWBO JT BMTP UIF BVUIPS PG UFYU PG UIF 5FYU
UZQF
BFTPO BUUPQBSTFD BOE XSFR 
"T JU IBQQFOT DSJUFSJPO DPNFT XJUI B QSFUUZ OJDF UVUPSJBM
CVU XFƊMM TUJMM XPSL UISPVHI BO FYBNQMF TP ZPV DBO GPMMPX BMPOH
XJUI UIJT DIBQUFS *O PVS UPZ QSPHSBN IFSF XFƊSF MPPLJOH UP
XSJUF B UPUBM WFSTJPO PG (!!) XIJDI SFUVSOT .BZCF UP NBLF
UIF CPUUPNT VOOFDFTTBSZ 8IFO ZPV DPNQJMF DPEF GPS CFODI
NBSLJOH NBLF TVSF ZPVƊSF VTJOH -O PS -O2 JO UIF CVJME ƷBHT UP
()$ 5IPTF DBO CF TQFDJƶFE CZ SVOOJOH ()$ NBOVBMMZ

-- with stack
$ stack ghc -- -O2 bench.hs

-- without stack
$ ghc -O2 bench.hs

0S WJB UIF $BCBM TFUUJOH ghc-options 


-FUƊT HFU PVS NPEVMF TFU VQ

http://hackage.haskell.org/package/text

http://hackage.haskell.org/package/aeson

http://hackage.haskell.org/package/attoparsec

http://hackage.haskell.org/package/wreq

http://www.serpentine.com/criterion/tutorial.html

https://www.haskell.org/cabal/users-guide/
$)"15&3  #"4*$ -*#3"3*&4 

module Main where

import Criterion.Main

infixl 9 !?
_ !? n | n < 0 = Nothing
[] !? _ = Nothing
(x:_) !? 0 = Just x
(_:xs) !? n = xs !? (n-1)

myList :: [Int]
myList = [1..9999]

main :: IO ()
main = defaultMain
[ bench "index list 9999"
$ whnf (myList !!) 9998
, bench "index list maybe index 9999"
$ whnf (myList !?) 9998
]

0VS WFSTJPO PG (!!) TIPVMEOƊU IBWF BOZUIJOH UPP TVSQSJT


JOH HPJOH PO 8F IBWF EFDMBSFE UIBU JUƊT B MFǒBTTPDJBUJOH
JOƶY PQFSBUPS infixl
XJUI B QSFDFEFODF PG  8F IBWFOƊU IBE
NVDI SFBTPO UP UBML BCPVU UIF BTTPDJBUJWJUZ PS ƶYJUZ PG PQFSB
$)"15&3  #"4*$ -*#3"3*&4 

UPST NVDI TJODF $IBQUFS  5IJT JT UIF TBNF BTTPDJBUJWJUZ BOE


QSFDFEFODF BT UIF OPSNBM (!!) PQFSBUPS JO CBTF
Criterion.Main JT UIF DPOWFOJFODF NPEVMF UP JNQPSU GSPN
DSJUFSJPO JG ZPVƊSF KVTU SVOOJOH CFODINBSLT JO B .BJO NPEVMF
6TVBMMZ ZPVƊMM IBWF B CFODINBSL TUBO[B JO ZPVS $BCBM ƶMF UIBU
CFIBWFT MJLF BO FYFDVUBCMF *UƊT BMTP QPTTJCMF UP EP JU BT B POFPƵ
VTJOH 4UBDL

$ stack build criterion


$ stack ghc -- -O2 benchIndex.hs
$ ./benchIndex

0VS main GVODUJPO VTFT B GVODUJPO GSPN DSJUFSJPO DBMMFE whnf


5IF GVODUJPOT whnf BOE nf BMTP JO DSJUFSJPO
BT ZPV NJHIU HVFTT
SFGFS UP XFBL IFBE OPSNBM GPSN BOE normal form SFTQFDUJWFMZ
8FBL IFBE OPSNBM GPSN BT XF TBJE CFGPSF FWBMVBUFT UP UIF
ƶSTU EBUB DPOTUSVDUPS 5IBU NFBOT UIBU JG ZPVS PVUFSNPTU EBUB
DPOTUSVDUPS JT B .BZCF JUƊT POMZ HPJOH UP FWBMVBUF FOPVHI UP
ƶOE PVU JG JUƊT B /PUIJOH PS B +VTU ƈ JG UIFSF JT B Just a JU XPOƊU
DPVOU UIF DPTU PG FWBMVBUJOH UIF Ԑ WBMVF
6TJOH nf XPVME NFBO ZPV XBOUFE UP JODMVEF UIF DPTU PG
GVMMZ FWBMVBUJOH UIF Ԑ BT XFMM BT UIF ƶSTU EBUB DPOTUSVDUPS 5IF
LFZ XIFO EFUFSNJOJOH XIFUIFS ZPV XBOU whnf PS nf JT UP UIJOL
BCPVU XIBU ZPVƊSF USZJOH UP CFODINBSL BOE JG SFBDIJOH UIF
ƶSTU EBUB DPOTUSVDUPS XJMM BDUVBMMZ EP BMM UIF XPSL ZPVƊSF USZJOH
UP NFBTVSF PS OPU 8FƊMM UBML NPSF BCPVU XIBU UIF EJƵFSFODF
JT IFSF BOE IPX UP EFDJEF XIJDI ZPV OFFE JO KVTU B CJU
$)"15&3  #"4*$ -*#3"3*&4 

*O PVS DBTF XIBU XF XBOU JT UP DPNQBSF UXP UIJOHT UIF


XFBL IFBE OPSNBM GPSN FWBMVBUJPO PG UIF PSJHJOBM JOEFYJOH
PQFSBUPS BOE UIBU PG PVS TBGF WFSTJPO BQQMJFE UP UIF TBNF MPOH
MJTU 8F POMZ OFFE XFBL IFBE OPSNBM GPSN CFDBVTF (!!) BOE
(!?) EPOƊU SFUVSO B EBUB DPOTUSVDUPS VOUJM UIFZƊWF EPOF UIF
XPSL BMSFBEZ BT XF DBO TFF CZ UBLJOH B MPPL BU UIF ƶSTU UISFF
DBTFT

_ !? n | n < 0 = Nothing
[] !? _ = Nothing
(x:_) !? 0 = Just x

5IFTF ƶSTU UISFF DBTFT BSFOƊU SFBDIFE VOUJM ZPVƊWF HPOF


UISPVHI UIF MJTU BT GBS BT ZPVƊSF HPJOH UP HP 5IF SFDVSTJWF DBTF
CFMPX EPFTOƊU SFUVSO B EBUB DPOTUSVDUPS *OTUFBE JU JOWPLFT
JUTFMG SFQFBUFEMZ VOUJM POF PG UIF BCPWF DBTFT JT SFBDIFE &WBM
VBUJOH UP 8)/' DBOOPU BOE EPFT OPU QBVTF JO B TFMGJOWPLFE
SFDVSTJWF DBTF MJLF UIJT

(_:xs) !? n = xs !? (n-1)
-- Self function call, not yet in weak head.

8IFO FWBMVBUFE UP XFBL IFBE OPSNBM GPSN UIF BCPWF XJMM


DPOUJOVF VOUJM JU SFBDIFT UIF JOEFY ZPV SFBDI UIF FMFNFOU PS
ZPV IJU UIF FOE PG UIF MJTU -FU VT DPOTJEFS BO FYBNQMF
$)"15&3  #"4*$ -*#3"3*&4 

[1, 2, 3] !? 2
-- matches final case

(_: [2, 3]) !? 2


= [2, 3] !? (2-1)
-- not a data constructor, keep going

[2, 3] !? 1
-- matches final case

(_: [3]) !? 1
= [3] !? (1-1)
-- not a data constructor, keep going

[3] !? 0
-- matches Just case

(x:[]) !? 0 = Just x
-- We stop at Just

*O UIF BCPWF XF IBQQFO UP LOPX ԧ JT  CVU JUƊMM HFU UIVOLFE


JG JU XBTOƊU PQQPSUVOJTUJDBMMZ FWBMVBUFE PO DPOTUSVDUJPO PG UIF
MJTU
/FYU MFUƊT MPPL BU UIF UZQFT PG UIF GPMMPXJOH GVODUJPOT
$)"15&3  #"4*$ -*#3"3*&4 

defaultMain :: [Benchmark] -> IO ()

whnf :: (a -> b) -> a -> Benchmarkable


nf :: Control.DeepSeq.NFData b =>
(a -> b) -> a -> Benchmarkable

5IF SFBTPO JU XBOUT B GVODUJPO JU DBO BQQMZ BO BSHVNFOU


UP JT TP UIBU UIF SFTVMU JTOƊU TIBSFE XIJDI XF EJTDVTTFE JO UIF
QSFWJPVT DIBQUFS 8F XBOU JU UP SFQFSGPSN UIF XPSL GPS FBDI
TBNQMJOH JO UIF CFODINBSL SFTVMUT TP UIJT EFTJHO QSFWFOUT
UIBU TIBSJOH ,FFQ JO NJOE UIBU JG ZPV XBOU UP VTF ZPVS PXO
EBUBUZQF XJUI OG XIJDI IBT BO /'%BUB DPOTUSBJOU ZPV XJMM
OFFE UP QSPWJEF ZPVS PXO JOTUBODF :PV DBO ƶOE FYBNQMFT JO
UIF EFFQTFR MJCSBSZ PO )BDLBHF
0VS HPBM XJUI UIJT FYBNQMF JT UP FRVBMJ[F UIF QFSGPSNBODF
EJƵFSFODF CFUXFFO (!?) BOE (!!) *O UIJT DBTF XFƊWF EFSJWFE
UIF JNQMFNFOUBUJPO PG (!?) GSPN UIF 3FQPSU WFSTJPO PG (!!)
)FSFƊT IPX JU MPPLT JO CBTF
$)"15&3  #"4*$ -*#3"3*&4 

-- Go to the Data.List docs in `base`,


-- click the source link for (!!)

#ifdef USE_REPORT_PRELUDE
xs !! n | n < 0 = error "Prelude.!!: negative index"
[] !! _ = error "Prelude.!!: index too large"
(x:_) !! 0 = x
(_:xs) !! n = xs !! (n-1)
#else

)PXFWFS BǒFS ZPV SVO UIF CFODINBSLT ZPVƊMM ƶOE PVS


WFSTJPO CBTFE PO UIF BCPWF JTOƊU RVJUF BT GBTU  'BJS FOPVHI *U
UVSOT PVU UIBU NPTU PG UIF UJNF XIFO UIFSFƊT B 3FQPSU WFSTJPO BT
XFMM BT B OPO3FQPSU WFSTJPO PG B GVODUJPO JO CBTF JUƊT CFDBVTF
UIFZ GPVOE B XBZ UP PQUJNJ[F JU BOE NBLF JU GBTUFS *G XF KVTU
MPPL EPXO GSPN UIF #else XF DBO ƶOE UIF WFSTJPO UIBU SFQMBDFE
JU

/PUF UIBU JG ZPV HFU XFJSE CFODINBSL SFTVMUT ZPVƊMM XBOU UP SFTPSU UP UIF PME QSP
HSBNNFSƊT USJDL PG XJQJOH ZPVS CVJME 8JUI 4UBDL ZPVƊE SVO stack clean XJUI $BCBM JUƊE
CF cabal clean *OFYQMJDBCMF UIJOHT IBQQFO TPNFUJNFT :PV TIPVMEOƊU OFFE UP EP UIJT
SFHVMBSMZ UIPVHI
$)"15&3  #"4*$ -*#3"3*&4 

-- negIndex and tooLarge are a bottom


-- and a const bottom respectively.

{-# INLINABLE (!!) #-}


xs !! n
| n < 0 = negIndex
| otherwise =
foldr (\x r k -> case k of
0 -> x
_ -> r (k-1)) tooLarge xs n

5IF OPO3FQPSU WFSTJPO JT XSJUUFO JO UFSNT PG foldr XIJDI


PǒFO CFOFƶUT GSPN UIF WBSJPVT SFXSJUF SVMFT BOE PQUJNJ[BUJPOT
BUUBDIFE UP foldr ƈ SVMFT XF XJMM OPU CF FYQMBJOJOH IFSF BU BMM
TPSSZ 5IJT WFSTJPO BMTP IBT B QSBHNB MFUUJOH ()$ LOPX JUƊT
PLBZ UP JOMJOF UIF DPEF PG UIF GVODUJPO XIFSF JUƊT VTFE XIFO
UIF DPTU FTUJNBUPS UIJOLT JUƊT XPSUIXIJMF UP EP TP 4P MFUƊT
DIBOHF PVS WFSTJPO PG UIJT PQFSBUPS UP NBUDI UIJT WFSTJPO UP
NBLF VTF PG UIPTF TBNF PQUJNJ[BUJPOT
$)"15&3  #"4*$ -*#3"3*&4 

infixl 9 !?
{-# INLINABLE (!?) #-}
xs !? n
| n < 0 = Nothing
| otherwise =
foldr (\x r k -> case k of
0 -> Just x
_ -> r (k-1)) (const Nothing) xs n

*G ZPV SVO UIJT ZPVƊMM ƶOE UIBUƒUIJOHT IBWF OPU JNQSPWFE 4P


XIBU DBO XF EP UP JNQSPWF UIF QFSGPSNBODF PG PVS PQFSBUPS
8FMM VOMFTT ZPV BEEFE POF BMSFBEZ ZPVƊMM OPUJDF UIF UZQF
TJHOBUVSF JT NJTTJOH *G ZPV BEE B EFDMBSBUJPO UIBU UIF OVNCFS
BSHVNFOU JT BO *OU JU TIPVME OPX QFSGPSN UIF TBNF BT UIF
PSJHJOBM

infixl 9 !?
{-# INLINABLE (!?) #-}
(!?) :: [a] -> Int -> Maybe a
xs !? n
| n < 0 = Nothing
| otherwise =
foldr (\x r k -> case k of
0 -> Just x
_ -> r (k-1)) (const Nothing) xs n
$)"15&3  #"4*$ -*#3"3*&4 

$IBOHF UIF GVODUJPO JO ZPVS NPEVMF UP SFƷFDU UIJT BOE SVO


UIF CFODINBSL BHBJO UP DIFDL
5IF JTTVF XBT UIBU UIF WFSTJPO XJUI BO JOGFSSFE UZQF XBT
EFGBVMUJOH UIF Num a => a UP *OUFHFS XIJDI DPNQJMFT UP B MFTT
FƸDJFOU WFSTJPO PG UIJT DPEF UIBO EPFT POF UIBU TQFDJƶFT UIF
UZQF *OU 5IF *OU WFSTJPO XJMM UVSO JOUP B NPSF QSJNJUJWF GBTUFS
MPPQ :PV DBO WFSJGZ UIJT GPS ZPVSTFMG CZ TQFDJGZJOH UIF UZQF
*OUFHFS BOE SFSVOOJOH UIF DPEF PS DPNQBSJOH UIF ()$ $PSF
PVUQVU GPS FBDI WFSTJPO

.PSF PO XIOG BOE OG


-FUƊT SFUVSO OPX UP UIF RVFTUJPO PG XIFO XF TIPVME VTF whnf
PS nf :PV XBOU UP VTF whnf XIFO UIF ƶSTU EBUB DPOTUSVDUPS JT B
NFBOJOHGVM JOEJDBUPS PG XIFUIFS UIF XPSL ZPVƊSF JOUFSFTUFE JO
IBT CFFO EPOF $POTJEFS UIF TJNQMJTUJD FYBNQMF PG B QSPHSBN
UIBU JT NFBOU UP MPDBUF TPNF EBUB JO B EBUBCBTF TBZ B QFSTPOƊT
OBNF BOE XIFUIFS UIFSF BSF BOZ LOPXO BEESFTTFT GPS UIBU
QFSTPO *G JU ƶOET BOZ EBUB JU NJHIU QSJOU UIBU JOGPSNBUJPO
JOUP B ƶMF
5IF QBSU ZPVƊSF QSPCBCMZ USZJOH UP KVEHF UIF QFSGPSNBODF PG
JT UIF MPPLVQ GVODUJPO UIBU ƶOET UIF EBUB BOE BTTFTTFT XIFUIFS
JU FYJTUT OPU IPX GBTU ZPVS DPNQVUFS DBO QSJOU UIF MJTU PG BE
ESFTTFT JOUP B ƶMF *O UIBU DBTF XIBU ZPV DBSF BCPVU JT BU UIF
MFWFM PG XFBL IFBE OPSNBM GPSN BOE whnf XJMM UFMM ZPV NPSF
QSFDJTFMZ IPX MPOH JU JT UBLJOH UP ƶOE UIF EBUB BOE EFDJEF
$)"15&3  #"4*$ -*#3"3*&4 

XIFUIFS ZPV IBWF B /PUIJOH PS B Just a


0O UIF PUIFS IBOE JG ZPV BSF JOUFSFTUFE JO NFBTVSJOH UIF
UJNF JU UBLFT UP QSJOU ZPVS SFTVMUT JO BEEJUJPO UP MPPLJOH VQ UIF
EBUB UIFO ZPV NBZ XBOU UP FWBMVBUF UP OPSNBM GPSN 5IFSF
BSF UJNFT XIFO NFBTVSJOH UIBU NBLFT TFOTF 8FƊMM TFF TPNF
FYBNQMFT TIPSUMZ
'PS OPX MFU VT DPOTJEFS FBDI JOEFYJOH PQFSBUPS UIF (!!)
UIBU FYJTUT JO CBTF BOE UIF POF XFƊWF XSJUUFO UIBU VTFT .BZCF
JOTUFBE PG CPUUPNT
*O UIF GPSNFS DBTF UIF ƶOBM SFTVMU IBT UIF UZQF Ԑ 5IF
GVODUJPO EPFTOƊU TUPQ SFDVSTJOH VOUJM JU FJUIFS SFUVSOT CPUUPN
PS UIF WBMVF BU UIBU JOEFY *O FJUIFS DBTF JUƊT EPOF BMM UIF XPSL
ZPVƊE DBSF UP NFBTVSF ƈ USBWFSTJOH UIF MJTU &WBMVBUJPO UP
8)/' NFBOT TUPQQJOH BU ZPVS Ԑ WBMVF
*O UIF MBUUFS DBTF XJUI .BZCF FWBMVBUJPO UP 8)/' NFBOT
TUPQQJOH BU FJUIFS +VTU PS /PUIJOH *U XPOƊU FWBMVBUF UIF DPO
UFOUT PG UIF +VTU EBUB DPOTUSVDUPS VOEFS whnf CVU JU XJMM VOEFS
nf &JUIFS JT TVƸDJFOU GPS UIF QVSQPTFT PG UIF CFODINBSL BT
BHBJO XFƊSF NFBTVSJOH IPX RVJDLMZ UIJT DPEF SFBDIFT UIF WBMVF
BU BO JOEFY JO UIF MJTU
-FU VT DPOTJEFS BO FYBNQMF XJUI B GFX KPUT BOE DIBOHFT
$)"15&3  #"4*$ -*#3"3*&4 

module Main where

import Criterion.Main
import Debug.Trace

myList :: [Int]
myList = trace "myList was evaluated"
([1..9999] ++ [undefined])

-- your version of (!?) here

main :: IO ()
main = defaultMain
[ bench "index list 9999"
$ whnf (myList !!) 9998
, bench "index list maybe index 9999"
$ nf (myList !?) 9999
]

/PUJDF XIBU XF EJE IFSF 8F BEEFE BO VOEFƶOFE JO XIBU


XJMM CF UIF JOEFY QPTJUJPO  8JUI UIF (!!) PQFSBUPS XF BSF
BDDFTTJOH UIF JOEFY KVTU CFGPSF UIBU CPUUPN WBMVF CFDBVTF UIFSF
JT OP PVUFS EBUB DPOTUSVDUPS TVDI BT /PUIJOH PS +VTU
XIFSF
XF DPVME TUPQ UIF FWBMVBUJPO #PUI whnf BOE nf XJMM OFDFTTBSJMZ
GPSDF UIBU CPUUPN WBMVF
$)"15&3  #"4*$ -*#3"3*&4 

8F BMTP NPEJƶFE UIF whnf UP nf GPS UIF CFODINBSL PG (!?)


/PX JU XJMM FWBMVBUF UIF VOEFƶOFE JU GPVOE BU UIBU JOEFY VOEFS
UIF CPUUPN JO UIF ƶSTU SVO PG UIF CFODINBSL BOE GBJM

benchmarking index list maybe index 9999


criterion1: Prelude.undefined

" GVODUJPO WBMVF UIBU SFUVSOFE CPUUPN JOTUFBE PG B EBUB


DPOTUSVDUPS XPVMEƊWF BMTP BDUFE BT B TUPQQJOH QPJOU GPS 8)/'
$POTJEFS UIF GPMMPXJOH

Prelude> (Just undefined) `seq` 1


1
Prelude> (\_ -> undefined) `seq` 1
1
Prelude> ((\_ -> Just undefined) 0) `seq` 1
1
Prelude> ((\_ -> undefined) 0) `seq` 1
*** Exception: Prelude.undefined

.VDI PG UIF UJNF whnf JT HPJOH UP DPWFS UIF UIJOH ZPVƊSF


USZJOH UP CFODINBSL

.BLJOH UIF DBTF GPS OG


-FU VT OPX MPPL BU BO FYBNQMF PG XIFO whnf JTOƊU TVƸDJFOU GPS
CFODINBSLJOH TPNFUIJOH UIBU VTFT HVBSEFE SFDVSTJPO VOMJLF
(!!)
$)"15&3  #"4*$ -*#3"3*&4 

module Main where

import Criterion.Main

myList :: [Int]
myList = [1..9999]

main :: IO ()
main = defaultMain
[ bench "map list 9999" $ whnf (map (+1)) myList
]

5IF BCPWF JT BO FYBNQMF PG HVBSEFE SFDVSTJPO CFDBVTF B EBUB


DPOTUSVDUPS JT JOUFSQPTFE CFUXFFO FBDI SFDVSTJPO TUFQ 5IF
EBUB DPOTUSVDUPS JT UIF DPOT DFMM XIFO XFƊSF UBMLJOH BCPVU NBQ
(VBSEFE SFDVSTJPO MFUT VT DPOTVNF UIF SFDVSTJPO TUFQT VQ UP
XFBL IFBE OPSNBM GPSN JODSFNFOUBMMZ PO EFNBOE
*NQPSUBOUMZ foldr DBO CF VTFE UP JNQMFNFOU HVBSEFE BOE
VOHVBSEFE SFDVSTJPO EFQFOEJOH FOUJSFMZ PO XIBU UIF GPMEJOH
GVODUJPO EPFT SBUIFS UIBO BOZ TQFDJBM QSPWJTJPO NBEF CZ foldr
JUTFMG 4P XIBU IBQQFOT XIFO XF CFODINBSL UIJT

Linking bin/bench ...


time 8.844 ns (8.670 ns .. 9.033 ns)
0.998 R² (0.997 R² .. 1.000 R²)
mean 8.647 ns (8.567 ns .. 8.751 ns)
$)"15&3  #"4*$ -*#3"3*&4 

std dev 293.3 ps (214.7 ps .. 412.9 ps)


variance introduced by outliers: 57% (severely inflated)

8FMM UIBUƊT TVTQFDU %PFT JU SFBMMZ UBLF  OBOPTFDPOET UP


USBWFSTF B   FMFNFOU MJOLFE MJTU JO )BTLFMM 8F KVTU TBX
BO FYBNQMF PG IPX MPOH JU TIPVME UBLF SPVHIMZ 5IJT JT BO
FYBNQMF PG PVS CFODINBSL CFJOH UPP MB[Z 5IF JTTVF JT UIBU
map VTFT HVBSEFE SFDVSTJPO BOE UIF DPOT DFMMT PG UIF MJTU BSF
JOUFSQPTFE CFUXFFO FBDI SFDVSTJPO PG map :PV NBZ SFDBMM UIJT
GSPN UIF MJTUT BOE GPMET DIBQUFST 4P JU FOET VQ FWBMVBUJOH
POMZ UIJT GBS

(_ : _)

"I UIBU ƶSTU EBUB DPOTUSVDUPS *U IBT OFJUIFS EPOF UIF XPSL
PG JODSFNFOUJOH UIF WBMVF OPS IBT JU USBWFSTFE UIF SFTU PG UIF
MJTU *UƊT KVTU TJUUJOH UIFSF BU UIF ƶSTU DPOT DFMM 6TJOH CPUUPNT
ZPV DBO QSPHSFTTJWFMZ QSPWF UP ZPVSTFMG XIBU whnf JT FWBMVBUJOH
CZ SFQMBDJOH UIJOHT BOE SFSVOOJOH UIF CFODINBSL
$)"15&3  #"4*$ -*#3"3*&4 

-- is it applying (+1)?
myList = (undefined : [2..9999])

-- Is it going any further in the list?


myList :: [Int]
myList = (undefined : undefined)

-- This should s'plode because it'll be looking


-- for that first data constructor or (->) to stop at
myList :: [Int]
myList = undefined

/P NBUUFS XF DBO ƶY UIJT

-- change this bit


whnf (map (+1)) myList

-- into:
nf (map (+1)) myList

5IFO XF HFU

time 122.5 μs (121.7 μs .. 123.9 μs)


0.999 R² (0.998 R² .. 1.000 R²)
mean 123.0 μs (122.0 μs .. 125.6 μs)
std dev 5.404 μs (2.806 μs .. 9.323 μs)
$)"15&3  #"4*$ -*#3"3*&4 

5IBU JT DPOTJEFSBCMZ NPSF SFBMJTUJD DPOTJEFSJOH XFƊWF FWBM


VBUFE UIF DPOTUSVDUJPO PG B XIPMF OFX MJTU 5IJT JT TMPXFS UIBO
UIF JOEFYJOH PQFSBUJPO CFDBVTF XFƊSF OPU KVTU LJDLJOH B OFX
WBMVF PVU XFƊSF BMTP DPOTUSVDUJOH B OFX MJTU
*O HFOFSBM XIFO EFDJEJOH CFUXFFO whnf BOE nf BTL ZPVSTFMG
ƌXIFO * IBWF SFBDIFE UIF ƶSTU EBUB DPOTUSVDUPS IBWF * EPOF
NPTU PS BMM PG UIF XPSL UIBU NBUUFST ƍ #F DBSFGVM OPU UP VTF nf
UPP NVDI *G ZPV IBWF B GVODUJPO UIBU SFUVSOT B OPOUSJWJBM EBUB
TUSVDUVSF PS DPMMFDUJPO GPS XIJDI JUƊT BMSFBEZ EPOF BMM UIF XPSL
UP QSPEVDF nf XJMM NBLF ZPVS DPEF MPPL FYDFTTJWFMZ TMPX BOE
MFBE ZPV PO B XJME HPPTF DIBTF

 1SPƶMJOH ZPVS QSPHSBNT


8FƊSF HPJOH UP EP PVS CFTU UP DPOWFZ XIBU ZPV TIPVME LOPX
BCPVU QSPƶMJOH QSPHSBNT XJUI ()$ BOE XIBU XF UIJOL JT DPO
DFQUVBMMZ MFTT XFMM DPWFSFE CVU XF BSFOƊU HPJOH UP QSFTVNF UP
SFQMBDF UIF ()$ 6TFS (VJEF 8F TUSPOHMZ SFDPNNFOE ZPV
SFBE UIF HVJEF GPS NPSF JOGPSNBUJPO

1SPƶMJOH UJNF VTBHF


4PNFUJNFT SBUIFS UIBO TFFJOH IPX GBTU PVS QSPHSBNT BSF XF
XBOU UP LOPX XIZ UIFZƊSF TMPX PS GBTU BOE XIFSF UIFZƊSF TQFOE

https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/profiling.html
$)"15&3  #"4*$ -*#3"3*&4 

JOH UIFJS UJNF 5P UIBU FOE XF VTF QSPƶMJOH 'JSTU MFUƊT QVU
UPHFUIFS B TJNQMF FYBNQMF GPS NPUJWBUJOH UIJT

-- profilingTime.hs
module Main where

f :: IO ()
f = do
print ([1..] !! 999999)
putStrLn "f"

g :: IO ()
g = do
print ([1..] !! 9999999)
putStrLn "g"

main :: IO ()
main = do
f
g

(JWFO UIBU XF USBWFSTF  UJNFT BT NVDI MJTU JO UIF DBTF PG


Ԗ XF CFMJFWF XF TIPVME TFF TPNFUIJOH MJLF  UJNFT BT NVDI
$16 UJNF TQFOU JO Ԗ 8F DBO EP UIF GPMMPXJOH UP EFUFSNJOF JG
UIBUƊT UIF DBTF
$)"15&3  #"4*$ -*#3"3*&4 

$ stack ghc -- -prof -fprof-auto -rtsopts -O2 profile.hs


./profile +RTS -P
cat profile.prof

#SFBLJOH EPXO XIBU FBDI ƷBH EPFT

 -prof FOBCMFT QSPƶMJOH 1SPƶMJOH JTOƊU FOBCMFE CZ EFGBVMU


CFDBVTF JU DBO MFBE UP TMPXFS QSPHSBNT CVU UIJT HFOFSBMMZ
JTOƊU BO JTTVF XIFO ZPVƊSF JOWFTUJHBUJOH UIF QFSGPSNBODF
PG ZPVS QSPHSBNT 6TFE BMPOF -prof XJMM SFRVJSF ZPV UP
BOOPUBUF ƌDPTU DFOUSFTƍ NBOVBMMZ QMBDFT GPS ()$ UP NBSL
GPS LFFQJOH USBDL PG IPX NVDI UJNF JT TQFOU FWBMVBUJOH
TPNFUIJOH

 -fprof-auto BTTJHOT BMM CJOEJOHT OPU NBSLFE JOMJOF B DPTU


DFOUFS OBNFE BǒFS UIF CJOEJOH 5IJT JT ƶOF GPS MJUUMF TUVƵ
PS PUIFSXJTF OPU UFSSJCMZ QFSGPSNBODFTFOTJUJWF TUVƵ CVU
JG ZPVƊSF EFBMJOH XJUI B MBSHF QSPHSBN PS POF TFOTJUJWF
UP QFSUVSCBUJPOT GSPN QSPƶMJOH JU NBZ CF CFUUFS UP OPU
VTF UIJT BOE JOTUFBE BTTJHO ZPVS ƌ4$$Tƍ NBOVBMMZ 4$$ JT
XIBU UIF ()$ EPDVNFOUBUJPO DBMMT B DPTU DFOUFS

 -rtsopts FOBCMFT ZPV UP QBTT ()$ 354 PQUJPOT UP UIF HFO


FSBUFE CJOBSZ 5IJT JT PQUJPOBM TP ZPV DBO HFU B TNBMMFS
CJOBSZ JG EFTJSFE 8F OFFE UIJT UP UFMM PVS QSPHSBN UP
EVNQ UIF QSPƶMF UP UIF .prof ƶMF OBNFE BǒFS PVS QSP
HSBN
$)"15&3  #"4*$ -*#3"3*&4 

 -O2 FOBCMFT UIF IJHIFTU MFWFM PG QSPHSBN PQUJNJ[BUJPOT


5IJT JT XJTF JG ZPV DBSF BCPVU QFSGPSNBODF CVU -O CZ JUTFMG
BMTP FOBCMFT PQUJNJ[BUJPOT BMCFJU TPNFXIBU MFTT BHHSFT
TJWF POFT &JUIFS PQUJPO DBO NBLF TFOTF XIFO CFODI
NBSLJOH JUƊT B DBTF CZ DBTF UIJOH CVU NPTU )BTLFMM QSP
HSBNNFST GFFM QSFUUZ GSFF UP EFGBVMU UP -O2

"ǒFS FYBNJOJOH UIF .prof ƶMF XIJDI DPOUBJOT UIF QSPƶMFS


PVUQVU UIJT JT SPVHIMZ XIBU XFƊMM TFF

Sun Feb 14 21:34 2016


Time and Allocation Profiling Report (Final)

profile +RTS -P -RTS

total time = 0.22 secs


(217 ticks @ 1000 us, 1 processor)
total alloc = 792,056,016 bytes
(excludes profiling overheads)

COST CENTRE MODULE %time %alloc ticks bytes

g Main 91.2 90.9 198 720004344


f Main 8.8 9.1 19 72012568

...later noise snipped,


we care about the above...
$)"15&3  #"4*$ -*#3"3*&4 

"OE JOEFFE  UJNF TQFOU JO Ԗ  UJNF TQFOU JO ԕ XPVME


TFFN UP WBMJEBUF PVS IZQPUIFTJT IFSF
5JNF JTOƊU UIF POMZ UIJOH XF DBO QSPƶMF 8FƊE BMTP MJLF
UP LOPX BCPVU UIF TQBDF PS NFNPSZ
EJƵFSFOU QBSUT PG PVS
QSPHSBN BSF SFTQPOTJCMF GPS VTJOH

1SPƶMJOH IFBQ VTBHF


8F IBWF NFBTVSFE UJNF OPX XF TIBMM NFBTVSF TQBDF 8FMM
NFNPSZ BOZXBZ XFƊSF OPU BTUSPQIZTJDJTUT 8FƊSF HPJOH UP
LFFQ UIJT RVJDL BOE CPSJOH TP UIBU XF NJHIU CF BCMF UP HFU UP
UIF HPPE TUVƵ

module Main where

import Control.Monad

blah :: [Integer]
blah = [1..1000]

main :: IO ()
main =
replicateM_ 10000 (print blah)

ghc -prof -fprof-auto -rtsopts -O2 loci.hs



.BZCF ZPV BSF CVU XFƊSF OPU *G ZPVƊSF BO BTUSPQIZTJDJTU QMFBTF FNBJM VT BT XF UIJOL
XF NFTTFE TPNFUIJOH VQ BOE DBOƊU DPMMBQTF UIF XPSNIPMF
$)"15&3  #"4*$ -*#3"3*&4 

./loci +RTS -hc -p


hp2ps loci.hp

*G ZPV PQFO UIF loci.ps QPTUTDSJQU ƶMF XJUI ZPVS 1%' SFBEFS
PG DIPJDF ZPVƊMM TFF IPX NVDI NFNPSZ UIF QSPHSBN VTFE
PWFS UIF UJNF UIF QSPHSBN SBO /PUF UIBU ZPVƊMM OFFE UIF
QSPHSBN UP SVO B NJOJNVN BNPVOU PG UJNF GPS UIF QSPƶMFS
UP HFU BOZ TBNQMFT PG UIF IFBQ TJ[F

 $POTUBOU BQQMJDBUJWF GPSNT


8IFO XFƊSF UBMLJOH BCPVU NFNPSZ VTBHF BOE TIBSJOH JO )BTLFMM
XF IBWF UP BMTP UBML BCPVU $"'T DPOTUBOU BQQMJDBUJWF GPSNT
$"'T BSF FYQSFTTJPOT UIBU IBWF OP GSFF WBSJBCMFT BOE BSF IFME
JO NFNPSZ UP CF TIBSFE XJUI BMM PUIFS FYQSFTTJPOT JO B NPEVMF
5IFZ DBO CF MJUFSBM WBMVFT PS QBSUJBMMZBQQMJFE GVODUJPOT BT
MPOH BT UIF BSHVNFOUT UP UIF GVODUJPO BSFOƊU OBNFE BSHVNFOUT

8FƊSF HPJOH UP DPOTUSVDU B WFSZ MBSHF $"' IFSF /PUJDF XF


BSF NBQQJOH PWFS BO JOƶOJUF MJTU BOE XBOU UP LOPX IPX NVDI
NFNPSZ UIJT VTFT :PV NJHIU DPOTJEFS CFUUJOH PO ƌB MPUƍ
$)"15&3  #"4*$ -*#3"3*&4 

module Main where

incdInts :: [Integer]
incdInts = map (+1) [1..]

main :: IO ()
main = do
print (incdInts !! 1000)
print (incdInts !! 9001)
print (incdInts !! 90010)
print (incdInts !! 9001000)
print (incdInts !! 9501000)
print (incdInts !! 9901000)

/PX XF DBO QSPƶMF UIBU

Thu Jan 21 23:25 2016


Time and Allocation Profiling Report (Final)

cafSaturation +RTS -p -RTS


total time = 0.28 secs
(283 ticks @ 1000 us, 1 processor)
total alloc = 1,440,216,712 bytes
(excludes profiling overheads)

COST CENTRE MODULE %time %alloc


$)"15&3  #"4*$ -*#3"3*&4 

incdInts Main 90.1 100.0


main Main 9.9 0.0

-- some irrelevant bits elided


COST CENTRE MODULE no. entries %time %alloc
MAIN MAIN 45 0 0.0 0.0
CAF Main 89 0 0.0 0.0
incdInts Main 91 1 90.1 100.0
main Main 90 1 9.9 0.0

/PUF IPX incdInts JT JUT PXO DPOTUBOU BQQMJDBUJWF GPSN $"'

IFSF BQBSU GSPN main "OE OPUJDF UIF TJ[F PG UIBU NFNPSZ
BMMPDBUJPO *UƊT CFDBVTF UIBU NBQQJOH PWFS BO JOƶOJUF MJTU JT B
UPQMFWFM WBMVF UIBU DBO CF TIBSFE UISPVHIPVU B NPEVMF TP JU
NVTU CF FWBMVBUFE BOE UIF SFTVMUT IFME JO NFNPSZ JO PSEFS UP
CF TIBSFE
$"'T JODMVEF

Ƒ WBMVFT

Ƒ QBSUJBMMZ BQQMJFE GVODUJPOT XJUIPVU OBNFE BSHVNFOUT

Ƒ GVMMZ BQQMJFE GVODUJPOT TVDI BT incdInts BCPWF BMUIPVHI


UIBU XPVME CF SBSF JO SFBM DPEF

$"'T DBO NBLF TPNF QSPHSBNT GBTUFS TJODF ZPV EPOƊU IBWF
UP LFFQ SFFWBMVBUJOH TIBSFE WBMVFT IPXFWFS $"'T DBO CF
DPNF NFNPSZJOUFOTJWF RVJUF RVJDLMZ 5IF JNQPSUBOU UBLF
$)"15&3  #"4*$ -*#3"3*&4 

BXBZ JT UIBU JG ZPV ƶOE ZPVS QSPHSBN VTJOH NVDI NPSF NFN
PSZ UIBO ZPV FYQFDUFE ƶOE UIF HPMEFO $"' BOE LJMM JU
'PSUVOBUFMZ $"'T NPTUMZ PDDVS JO UPZ DPEF 3FBM XPSME
DPEF JT VTVBMMZ QVMMJOH UIF EBUB GSPN TPNFXIFSF XIJDI BWPJET
UIF QSPCMFN PG IPMEJOH MBSHF BNPVOUT PG EBUB JO NFNPSZ
-FUƊT MPPL BU B XBZ UP BWPJE DSFBUJOH B $"' CZ JOUSPEVDJOH
BO BSHVNFOU JOUP PVS incdInts FYBNQMF

module Main where

-- not a CAF
incdInts :: [Integer] -> [Integer]
incdInts x = map (+1) x

main :: IO ()
main = do
print (incdInts [1..] !! 1000)

*G ZPV FYBNJOF UIF QSPƶMF

CAF
main
incdInts

1PJOUGSFF UPQMFWFM EFDMBSBUJPOT XJMM CF $"'T CVU QPJOUGVM


POFT XJMM OPU 8FƊE EJTDVTTFE UIJT UP TPNF EFHSFF JO UIF QSF
WJPVT DIBQUFS BT XFMM 5IF SFBTPO UIF EJƵFSFODF NBUUFST JT
$)"15&3  #"4*$ -*#3"3*&4 

PǒFO OPU CFDBVTF PG UIF UPUBM BMMPDBUJPO SFQPSUFE CZ UIF QSP


ƶMF XIJDI JT PǒFO NJTMFBEJOH BOZXBZ 3BUIFS JUƊT JNQPSUBOU
CFDBVTF MJTUT BSF BT NVDI DPOUSPM TUSVDUVSFT BT EBUB TUSVDUVSFT
BOE JUƊT WFSZ DIFBQ JO ()$ UP DPOTUSVDU B MJTU XIJDI JT UISPXO
BXBZ JNNFEJBUFMZ %PJOH TP NJHIU JODSFBTF IPX NVDI NFN
PSZ ZPV BMMPDBUF JO UPUBM CVU VOMJLF B $"' JU XPOƊU TUBZ JO ZPVS
IFBQ XIJDI NBZ MFBE UP MPXFS QFBL NFNPSZ VTBHF BOE UIF
SVOUJNF TQFOEJOH MFTT UJNF DPMMFDUJOH HBSCBHF
*OEFFE UIJT JT OPU B TUBOEBMPOF $"' #VU XIBU JG XF FUB
SFEVDF JU UIBU JT SFNPWF JUT OBNFE BSHVNFOUT
TP UIBU JU JT
QPJOUGSFF

module Main where

-- Gonna be a CAF this time.


incdInts :: [Integer] -> [Integer]
incdInts = map (+1)

main :: IO ()
main = do
print (incdInts [1..] !! 1000)

5IJT UJNF XIFO ZPV MPPL BU UIF QSPƶMF JUƊMM CF JUT PXO $"'

CAF
incdInts
$)"15&3  #"4*$ -*#3"3*&4 

main
incdInts

(3&"5 4$055
*U EPFTOƊU SFBMMZ DIBOHF UIF QFSGPSNBODF GPS TPNFUIJOH TP
USJWJBM CVU ZPV HFU UIF JEFB 5IF CJH EJƵFSFODF CFUXFFO UIF
UXP JT JO UIF IFBQ QSPƶMFT $IFDL UIFN BOE ZPV XJMM MJLFMZ TFF
XIBU XF NFBO

 .BQ
8FƊSF HPJOH UP TUBSU PVS FYQMPSBUJPO PG EBUB TUSVDUVSFT XJUI
.BQ CVU JUƊT XPSUI QPJOUJOH PVU IFSF UIBU NPTU PG UIF TUSVD
UVSFT XFƊMM MPPL BU BSF JO TPNF TFOTF SFQMBDFNFOUT GPS UIF MJTUT
XF IBWF EFQFOEFE PO UISPVHIPVU UIF CPPL -JTUT BOE TUSJOHT
BSF VTFGVM GPS B MPU PG UIJOHT CVU UIFZƊSF OPU BMXBZT UIF NPTU
QFSGPSNBOU PS FWFO UIF NPTU VTFGVM XBZ UP TUSVDUVSF ZPVS EBUB
8IBU JT UIF NPTU QFSGPSNBOU PS VTFGVM GPS BOZ HJWFO QSPHSBN
DBO WBSZ TP XF DBOƊU HJWF B CMBOLFU SFDPNNFOEBUJPO UIBU ZPV
TIPVME BMXBZT VTF BOZ POF PG UIF TUSVDUVSFT XFƊSF HPJOH UP UBML
BCPVU :PV IBWF UP KVEHF UIBU CBTFE PO XIBU QSPCMFNT ZPVƊSF
USZJOH UP TPMWF BOE VTF CFODINBSLJOH BOE QSPƶMJOH UPPMT UP
IFMQ ZPV ƶOF UVOF UIF QFSGPSNBODF
.PTU PG UIF EBUB TUSVDUVSFT XFƊMM CF MPPLJOH BU BSF JO UIF
DPOUBJOFST MJCSBSZ *G ZPV CVJME JU .BQ XJMM DPNF "OE BMTP

http://hackage.haskell.org/package/containers
$)"15&3  #"4*$ -*#3"3*&4 

4FRVFODF BOE 4FU BOE TPNF PUIFS HPPEJFT :PVƊMM OPUJDF B MPU
PG UIF EBUB TUSVDUVSFT IBWF B TJNJMBS "1* CVU FBDI BSF EFTJHOFE
GPS EJƵFSFOU TFUT PG DJSDVNTUBODFT
8FƊWF VTFE UIF .BQ UZQF CFGPSF UP SFQSFTFOU BTTPDJBUJPOT PG
VOJRVF QBJSJOHT PG LFZT UP WBMVFT :PV NBZ SFNFNCFS JU GSPN
UIF 5FTUJOH DIBQUFS JO QBSUJDVMBS XIFSF XF VTFE JU UP MPPL VQ
.PSTF DPEF USBOTMBUJPOT PG BMQIBCFUJD DIBSBDUFST 5IPTF XFSF
GVO UJNFT TP DBSFGSFF BOE JOOPDFOU
5IF TUSVDUVSF PG UIF .BQ UZQF MPPLT MJLF UIJT

data Map k a
= Bin {-# UNPACK #-} !Size !k a !(Map k a) !(Map k a)
| Tip

type Size = Int

:PV NBZ SFDPHOJ[F UIF FYDMBNBUJPO NBSLT EFOPUJOH TUSJDU


OFTT GSPN UIF TFDUJPOT PO CBOH QBUUFSOT JO UIF QSFWJPVT DIBQUFS
5JQ JT B EBUB DPOTUSVDUPS GPS DBQQJOH PƵ UIF CSBODI PG B USFF
*G ZPVƊE MJLF UP ƶOE PVU BCPVU UIF VOQBDLJOH PG TUSJDU ƶFMET
XIJDI JT XIBU UIF 6/1"$, QSBHNB JT GPS TFF UIF ()$ EPDV
NFOUBUJPO GPS NPSF JOGPSNBUJPO

https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#
unpack-pragma
$)"15&3  #"4*$ -*#3"3*&4 

8IBUƊT TPNFUIJOH UIBUƊT GBTUFS XJUI .BQ


8FMM MPPLVQT CZ LFZ JO QBSUJDVMBS BSF XIBU JUƊT VTFE GPS $PO
TJEFS UIF GPMMPXJOH DPNQBSJTPO PG BO BTTPDJBUJPO MJTU BOE %BUB.BQ

module Main where

import Criterion.Main
import qualified Data.Map as M

genList :: Int -> [(String, Int)]


genList n = go n []
where go 0 xs = ("0", 0) : xs
go n' xs = go (n' - 1) ((show n', n') : xs)

pairList :: [(String, Int)]


pairList = genList 9001
$)"15&3  #"4*$ -*#3"3*&4 

testMap :: M.Map String Int


testMap = M.fromList pairList

main :: IO ()
main = defaultMain
[ bench "lookup one thing, list" $
whnf (lookup "doesntExist") pairList
, bench "lookup one thing, map" $
whnf (M.lookup "doesntExist") testMap
]

"TTPDJBUJPO MJTUT TVDI BT pairList BSF ƶOF JG ZPV OFFE TPNF


UIJOH DIFBQ BOE DIFFSGVM GPS B WFSZ TNBMM TFSJFT PG QBJST CVU
ZPVƊSF CFUUFS PƵ VTJOH .BQ CZ EFGBVMU XIFO ZPV IBWF LFZT BOE
WBMVFT :PV HFU B IBOEZ TFU PG CBLFEJO GVODUJPOT GPS MPPLJOH
UIJOHT VQ BOE BO FƸDJFOU NFBOT PG EPJOH TP *OTFSU PQFSBUJPOT
BMTP CFOFƶU GSPN CFJOH BCMF UP ƶOE UIF FYJTUJOH LFZWBMVF QBJS
JO .BQ NPSF RVJDLMZ UIBO JO BTTPDJBUJPO MJTUT

8IBUƊT TMPXFS XJUI .BQ


6TJOH BO *OU BT ZPVS LFZ UZQF JT VTVBMMZ B TJHO ZPVƊE CF CFUUFS
PƵ XJUI B )BTI.BQ *OU.BQ PS 7FDUPS EFQFOEJOH PO UIF
TFNBOUJDT PG ZPVS QSPCMFN *G ZPV OFFE HPPE NFNPSZ EFOTJUZ
BOE MPDBMJUZ ƈ XIJDI XJMM NBLF BHHSFHBUJOH BOE SFBEJOH WBMVFT
$)"15&3  #"4*$ -*#3"3*&4 

PG B MBSHF 7FDUPS GBTUFS UIFO .BQ NJHIU CF JOBQQSPQSJBUF BOE


ZPVƊMM XBOU 7FDUPS JOTUFBE

 4FU
5IJT JT BMTP JO DPOUBJOFST *UƊT MJLF B .BQ CVU XJUIPVU UIF ƉWBMVFƊ
QBSU PG UIF ƉLFZ WBMVFƊ QBJS :PV NBZ CF BTLJOH ZPVSTFMG XIZ
EP * KVTU XBOU LFZT
8IFO XF VTF .BQ JU IBT BO 0SE DPOTUSBJOU PO UIF GVODUJPOT
UP FOTVSF UIF LFZT BSF JO PSEFS 5IBU JT POF PG UIF UIJOHT UIBU
NBLFT MPPLVQT JO .BQ QBSUJDVMBSMZ FƸDJFOU ,OPXJOH UIBU UIF
LFZT XJMM CF PSEFSFE EJWJEFT UIF QSPCMFNTQBDF VQ CZ IBMWFT
JG XFƊSF MPPLJOH GPS UIF LFZ  JO B TFU PG LFZT GSPN  XF EPOƊU
IBWF UP TFBSDI JO UIF ƶSTU IBMG PG UIF TFU CFDBVTF UIPTF OVNCFST
BSF MFTT UIBO  4FU MJLF .BQ JT TUSVDUVSFE BTTPDJBUJWFMZ OPU
MJOFBSMZ
'VODUJPOT XJUI 4FU IBWF UIF TBNF 0SE DPOTUSBJOU CVU OPX
XF EPOƊU IBWF LFZWBMVF QBJST ƈ XF KVTU IBWF LFZT "OPUIFS
XBZ UP UIJOL PG JU JT UIF LFZT BSF OPX UIF WBMVFT 5IBU NFBOT
UIBU 4FU SFQSFTFOUT B VOJRVF PSEFSFE TFU PG WBMVFT
)FSF JT UIF EBUBUZQF GPS 4FU
$)"15&3  #"4*$ -*#3"3*&4 

data Set a
= Bin {-# UNPACK #-} !Size !a !(Set a) !(Set a)
| Tip

type Size = Int

*UƊT FƵFDUJWFMZ FRVJWBMFOU UP B .BQ UZQF XJUI VOJU WBMVFT

module Main where

import Criterion.Main
import qualified Data.Map as M
import qualified Data.Set as S

bumpIt (i, v) = (i + 1, v + 1)

m :: M.Map Int Int


m = M.fromList $ take 10000 stream
where stream = iterate bumpIt (0, 0)

s :: S.Set Int
s = S.fromList $ take 10000 stream
where stream = iterate (+1) 0
$)"15&3  #"4*$ -*#3"3*&4 

membersMap :: Int -> Bool


membersMap i = M.member i m

membersSet :: Int -> Bool


membersSet i = S.member i s

main :: IO ()
main = defaultMain
[ bench "member check map" $
whnf membersMap 9999
, bench "member check set" $
whnf membersSet 9999
]

*G ZPV CFODINBSL UIF BCPWF ZPV TIPVME HFU WFSZ TJNJMBS


SFTVMUT GPS CPUI XJUI .BQ QFSIBQT CFJOH KVTU B TNJEHFO TMPXFS
UIBO 4FU 5IFZƊSF TJNJMBS CFDBVTF UIFZƊSF OFBSMZ JEFOUJDBM EBUB
TUSVDUVSFT JO UIF DPOUBJOFST MJCSBSZ
5IFSFƊT OPU NVDI NPSF UP TBZ *U IBT UIF TBNF QSPT BOE
DPOT BT .BQ XJUI UIF TBNF QFSGPSNBODF PG UIF DPSF PQFSB
UJPOT TBWF UIBU ZPVƊSF NPSF MJNJUFE

&YFSDJTF #FODINBSL 1SBDUJDF


.BLF B CFODINBSL UP QSPWF GPS ZPVSTFMG JG .BQ BOE 4FU IBWF
TJNJMBS QFSGPSNBODF PS OPU 5SZ PQFSBUJPOT PUIFS UIBO NFN

)" )" (&5 *5 
$)"15&3  #"4*$ -*#3"3*&4 

CFSTIJQ UFTUJOH TVDI BT JOTFSUJPO PS VOJPOT

 4FRVFODF
4FRVFODF JT B OJǒZ EBUBUZQF CVJMU BUPQ ƶOHFS USFFT XF BSFOƊU
HPJOH UP BEESFTT ƶOHFS USFFT JO UIJT CPPL VOGPSUVOBUFMZ CVU
XF FODPVSBHF ZPV UP DIFDL UIFN PVU 4FRVFODF BQQFOET
DIFBQMZ PO UIF GSPOU BOE UIF CBDL XIJDI BWPJET B DPNNPO
QSPCMFN XJUI MJTUT XIFSF ZPV DBO POMZ DPOT UP UIF GSPOU DIFBQMZ
)FSF JT UIF EBUBUZQF GPS 4FRVFODF

newtype Seq a = Seq (FingerTree (Elem a))

-- Elem is so elements and nodes can be


-- distinguished in the types of the
-- implementation. Don't sweat it.
newtype Elem a = Elem { getElem :: a }

data FingerTree a
= Empty
| Single a
| Deep {-# UNPACK #-} !Int !(Digit a)
(FingerTree (Node a)) !(Digit a)

https://en.wikipedia.org/wiki/Finger_tree
$)"15&3  #"4*$ -*#3"3*&4 

8IBUƊT GBTUFS XJUI 4FRVFODF


6QEBUFT DPOT BOE BQQFOE
UP CPUI FOET PG UIF EBUB TUSVDUVSF
BOE DPODBUFOBUJPO BSF XIBU 4FRVFODF JT QBSUJDVMBSMZ LOPXO
GPS :PV XPOƊU XBOU UP SFTPSU UP VTJOH 4FRVFODF CZ EFGBVMU
UIPVHI BT UIF MJTU UZQF JT PǒFO DPNQFUJUJWF 4FRVFODF XJMM
IBWF NPSF FƸDJFOU BDDFTT UP UIF UBJM UIBO B MJTU XJMM )FSFƊT BO
FYBNQMF XIFSF 4FRVFODF EPFT CFUUFS CFDBVTF UIF MJTU JT B CJU
CJH
$)"15&3  #"4*$ -*#3"3*&4 

module Main where

import Criterion.Main
import qualified Data.Sequence as S

lists :: [[Int]]
lists = replicate 10 [1..100000]

seqs :: [S.Seq Int]


seqs = replicate 10 (S.fromList [1..100000])

main :: IO ()
main = defaultMain
[ bench "concatenate lists" $
nf mconcat lists
, bench "concatenate sequences" $
nf mconcat seqs
]

/PUF UIBU JO UIF BCPWF B TVCTUBOUJBM BNPVOU PG UIF UJNF JO


UIF CFODINBSL JT TQFOU USBWFSTJOH UIF EBUB TUSVDUVSF CFDBVTF
XFƊSF FWBMVBUJOH UP OPSNBM GPSN UP FOTVSF BMM UIF XPSL JT EPOF
*ODJEFOUBMMZ UIJT BDDFOUVBUFT UIF EJƵFSFODF CFUXFFO -JTU BOE
4FRVFODF CFDBVTF JUƊT GBTUFS UP JOEFY PS USBWFSTF B TFRVFODF
UIBO B MJTU $POTJEFS UIF GPMMPXJOH
$)"15&3  #"4*$ -*#3"3*&4 

module Main where

import Criterion.Main
import qualified Data.Sequence as S

lists :: [Int]
lists = [1..100000]

seqs :: S.Seq Int


seqs = S.fromList [1..100000]

main :: IO ()
main = defaultMain
[ bench "indexing list" $
whnf (\xs -> xs !! 9001) lists
, bench "indexing sequence" $
whnf (flip S.index 9001) seqs
]

5IF EJƵFSFODF CFUXFFO MJTU BOE TFRVFODF JO UIF BCPWF XIFO


XF SBO UIF CFODINBSL XBT UXP PSEFST PG NBHOJUVEF

8IBUƊT TMPXFS XJUI 4FRVFODF


4FRVFODF JT B QFSTJTUFOU EBUB TUSVDUVSF MJLF .BQ TP UIF NFN
PSZ EFOTJUZ JTOƊU BT HPPE BT JU JT XJUI 7FDUPS XFƊSF HFUUJOH UIFSF

$)"15&3  #"4*$ -*#3"3*&4 

*OEFYJOH CZ *OU XJMM CF GBTUFS XJUI 7FDUPS BT XFMM -JTU XJMM CF


GBTUFS XJUI DPOTJOH BOE DPODBUFOBUJPO JO TPNF DBTFT JG UIF
MJTUT BSF TNBMM 8IFO ZPV LOPX ZPV OFFE DIFBQ BQQFOEJOH
UP UIF FOE PG B MPOH MJTU JUƊT XPSUI HJWJOH 4FRVFODF B USZ CVU
JUƊT CFUUFS UP CBTF UIF ƶOBM EFDJTJPO PO CFODINBSLJOH EBUB JG
QFSGPSNBODF NBUUFST

 7FDUPS
5IF OFYU EBUB TUSVDUVSF XFƊSF HPJOH UP MPPL BU JT OPU JO DPOUBJO
FST *UƊT JO JUT PXO MJCSBSZ DBMMFE VOTVSQSJTJOHMZ WFDUPS  :PVƊMM
OPUJDF JU TBZT WFDUPST BSF ƌFƸDJFOU BSSBZTƍ 8FƊSF OPU HPJOH UP
MPPL BU BSSBZT PS )BTLFMMƊT "SSBZ UZQF TQFDJƶDBMMZ IFSF UIPVHI
ZPV NBZ BMSFBEZ CF GBNJMJBS XJUI UIF JEFB
0OF SBSFMZ VTFT BSSBZT PS NPSF TQFDJƶDBMMZ "SSBZ JO
)BTLFMM 7FDUPS JT BMNPTU BMXBZT XIBU ZPV XBOU JOTUFBE PG BO BS
SBZ 5IF EFGBVMU 7FDUPS UZQF JT JNQMFNFOUFE BT B TMJDF XSBQQFS
PG "SSBZ XF DBO TFF UIJT JO UIF EFƶOJUJPO PG UIF EBUBUZQF

-- | Boxed vectors, supporting efficient slicing.


data Vector a = Vector {-# UNPACK #-} !Int
{-# UNPACK #-} !Int
{-# UNPACK #-} !(Array a)
deriving ( Typeable )

https://hackage.haskell.org/package/vector

http://hackage.haskell.org/package/array
$)"15&3  #"4*$ -*#3"3*&4 

5IFSF BSF NBOZ WBSJBOUT PG 7FDUPS BMUIPVHI XF XPOƊU EJT


DVTT UIFN BMM IFSF 5IFTF JODMVEF CPYFE VOCPYFE JNNVUBCMF
NVUBCMF BOE TUPSBCMF WFDUPST CVU UIF QMBJO WFSTJPO BCPWF JT
UIF VTVBM POF ZPVƊE VTF 8FƊMM UBML BCPVU NVUBCMF WFDUPST JO
UIFJS PXO TFDUJPO ƌ#PYFEƍ NFBOT UIF WFDUPS DBO SFGFSFODF BOZ
EBUBUZQF ZPV XBOU ƌVOCPYFEƍ SFQSFTFOUT SBX WBMVFT XJUIPVU
QPJOUFS JOEJSFDUJPO 5IF MBUUFS DBO TBWF B MPU PG NFNPSZ CVU
JT MJNJUFE UP UZQFT MJLF #PPM $IBS %PVCMF 'MPBU *OU 8PSE
UVQMFT PG VOCPYBCMF WBMVFT BOE UIF WBSJPVT TJ[FT PG *OU BOE
8PSE 4JODF B OFXUZQF JT VOMJǒFE BOE EPFTOƊU JOUSPEVDF BOZ
QPJOUFS JOEJSFDUJPO ZPV DBO VOCPY BOZ OFXUZQF UIBU DPOUBJOT
BO VOCPYBCMF UZQF

8IFO EPFT POF XBOU B 7FDUPS JO )BTLFMM


:PV XBOU B 7FDUPS XIFO

Ƒ ZPV OFFE NFNPSZ FƸDJFODZ DMPTF UP UIF UIFPSFUJDBM NBY


JNVN GPS UIF EBUB ZPV BSF XPSLJOH XJUI

Ƒ ZPVS EBUB BDDFTT JT BMNPTU FYDMVTJWFMZ JO UFSNT PG JOEFYJOH


WJB BO *OU WBMVF

Ƒ ZPV XBOU VOJGPSN BDDFTT UJNFT GPS BDDFTTJOH FBDI FMFNFOU


JO UIF EBUB TUSVDUVSF BOEPS

5IJT CPPL JTOƊU SFBMMZ UIF SJHIU QMBDF UP UBML BCPVU XIBU QPJOUFST BSF JO EFUBJM #SJFƷZ
UIFZ BSF SFGFSFODFT UP UIJOHT JO NFNPSZ SBUIFS UIBO UIF UIJOHT UIFNTFMWFT
$)"15&3  #"4*$ -*#3"3*&4 

Ƒ ZPV XJMM DPOTUSVDU B 7FDUPS PODF BOE SFBE JU NBOZ UJNFT


BMUFSOBUJWFMZ ZPV QMBO UP VTF B NVUBCMF WFDUPS GPS POHP
JOH FƸDJFOU VQEBUFT


8IBUƊT UIJT BCPVU TMJDJOH


3FNFNCFS UIJT MJOF GSPN UIF EFƶOJUJPO PG 7FDUPS

-- | Boxed vectors, supporting efficient slicing.

ƌ4MJDJOHƍ SFGFST UP TMJDJOH PƵ B QPSUJPO PS DSFBUJOH B TVC


BSSBZ 5IF 7FDUPS UZQF JT EFTJHOFE GPS NBLJOH TMJDJOH NVDI
DIFBQFS UIBO JU PUIFSXJTF XPVME CF $POTJEFS UIF GPMMPXJOH
$)"15&3  #"4*$ -*#3"3*&4 

module Main where

import Criterion.Main
import qualified Data.Vector as V

slice :: Int -> Int -> [a] -> [a]


slice from len xs =
take len (drop from xs)

l :: [Int]
l = [1..1000]

v :: V.Vector Int
v = V.fromList [1..1000]

main :: IO ()
main = defaultMain
[ bench "slicing list" $
whnf (head . slice 100 900) l
, bench "slicing vector" $
whnf (V.head . V.slice 100 900) v
]

*G ZPV SVO UIJT CFODINBSL 7FDUPS TIPVME CF  UJNFT


GBTUFS UIBO MJTU 8IZ #FDBVTF XIFO XF DPOTUSVDUFE UIBU OFX
$)"15&3  #"4*$ -*#3"3*&4 

7FDUPS XJUI V.slice BMM JU IBE UP EP XBT UIF GPMMPXJOH

-- from Data.Vector

instance G.Vector Vector a where


-- other methods elided
{-# INLINE basicUnsafeSlice #-}
basicUnsafeSlice j n (Vector i _ arr) =
Vector (i+j) n arr

8IBU NBLFT 7FDUPS OJDFS UIBO MJTUT BOE "SSBZ JO UIJT SFTQFDU
JT UIBU XIFO ZPV DPOTUSVDU B TMJDF PS ƌWJFXƍ PG BOPUIFS 7FDUPS
JU EPFTOƊU IBWF UP DPOTUSVDU BT NVDI OFX EBUB *U SFUVSOT B
OFX XSBQQFS BSPVOE UIF PSJHJOBM VOEFSMZJOH BSSBZ XJUI B OFX
JOEFY BOE PƵTFU XJUI B SFGFSFODF UP UIF TBNF PSJHJOBM "SSBZ
%PJOH UIF TBNF XJUI BO PSEJOBSZ "SSBZ PS B MJTU XPVMEƊWF
SFRVJSFE DPQZJOH NPSF EBUB 4QFFE DPNFT GSPN CFJOH TOFBLZ
BOE TLJQQJOH XPSL

6QEBUJOH WFDUPST
1FSTJTUFOU WFDUPST BSF OPU HSFBU BU IBOEMJOH VQEBUFT PO BO
POHPJOH CBTJT CVU UIFSF BSF TPNF TJUVBUJPOT JO XIJDI UIFZ DBO
TVSQSJTF ZPV 0OF TVDI DBTF JT GVTJPO  'VTJPO PS MPPQ GVTJPO

4USFBN 'VTJPO %VODBO $PVUUT http://code.haskell.org/~dons/papers/icfp088-coutts.
pdf
$)"15&3  #"4*$ -*#3"3*&4 

NFBOT UIBU BT BO PQUJNJ[BUJPO UIF DPNQJMFS DBO GVTF TFWFSBM


MPPQT JOUP POF NFHBMPPQ BOE EP JU JO POF QBTT

module Main where

import Criterion.Main
import qualified Data.Vector as V

testV' :: Int -> V.Vector Int


testV' n =
V.map (+n) $ V.map (+n) $
V.map (+n) $ V.map (+n)
(V.fromList [1..10000])

testV :: Int -> V.Vector Int


testV n =
V.map ( (+n) . (+n)
. (+n) . (+n) ) (V.fromList [1..10000])

main :: IO ()
main = defaultMain
[ bench "vector map prefused" $
whnf testV 9998
, bench "vector map will be fused" $
whnf testV' 9998
]
$)"15&3  #"4*$ -*#3"3*&4 

5IF WFDUPS MJCSBSZ IBT MPPQ GVTJPO CVJMU JO TP JO B MPU PG


DBTFT TVDI BT XJUI NBQQJOH ZPV XPOƊU DPOTUSVDU  WFDUPST KVTU
CFDBVTF ZPV NBQQFE GPVS UJNFT 5ISPVHI UIF VTF PG ()$
36-&4 UIF DPEF JO UFTU7Ɗ XJMM DIBOHF JOUP XIBU ZPV TFF JO
UFTU7 *UƊT XPSUI OPUJOH UIBU QBSU PG UIF SFBTPO UIJT PQUJNJ[BUJPO
JT TPVOE JT CFDBVTF XF LOPX XIBU DPEF QFSGPSNT FƵFDUT BOE
XIBU EPFT OPU CFDBVTF XF IBWF UZQFT
)PXFWFS MPPQ GVTJPO JTOƊU B QBOBDFB BOE UIFSF XJMM CF TJU
VBUJPOT XIFSF ZPV SFBMMZ KVTU XBOU UP DIBOHF POF FMFNFOU BU
B UJNF TFMFDUJWFMZ -FUƊT DPOTJEFS NPSF FƸDJFOU XBZT PG VQ
EBUJOH WFDUPST 8FƊSF HPJOH UP VTF UIF (//) PQFSBUPS GSPN UIF
WFDUPS MJCSBSZ IFSF *UƊT B CBUDI VQEBUF PQFSBUPS UIBU BMMPXT ZPV
UP NPEJGZ TFWFSBM FMFNFOUT PG UIF WFDUPS BU POF UJNF

module Main where

import Criterion.Main
import Data.Vector ((//))
import qualified Data.Vector as V

vec :: V.Vector Int


vec = V.fromList [1..10000]

https://wiki.haskell.org/GHC/Using_rules
$)"15&3  #"4*$ -*#3"3*&4 

slow :: Int -> V.Vector Int


slow n = go n vec
where go 0 v = v
go n v = go (n-1) (v // [(n, 0)])

batchList :: Int -> V.Vector Int


batchList n = vec // updates
where updates = fmap (\n -> (n, 0)) [0..n]

main :: IO ()
main = defaultMain
[ bench "slow" $ whnf slow 9998
, bench "batch list" $ whnf batchList 9998
]

5IF JTTVF XJUI UIF ƶSTU FYBNQMF JT UIBU XFƊSF VTJOH B CBUDI
"1*ƒ CVU OPU JO CBUDI *UƊT NVDI DIFBQFS ƇY JO PVS
UFTUT
UP DPOTUSVDU UIF MJTU PG VQEBUFT BMM BU PODF BOE UIFO GFFE
UIFN UP UIF (//) GVODUJPO 8F DBO NBLF JU FWFO GBTUFS TUJMM CZ
VTJOH UIF VQEBUF GVODUJPO UIBU VTFT B WFDUPS PG VQEBUFT

batchVector :: Int -> V.Vector Int


batchVector n = V.unsafeUpdate vec updates
where updates = fmap (\n -> (n, 0)) (V.fromList [0..n])
$)"15&3  #"4*$ -*#3"3*&4 

#FODINBSLJOH UIJT WFSTJPO TIPVME HFU ZPV DPEF UIBU JT BCPVU


Y GBTUFS #VU XFƊSF HSFFEZ 4P XF XBOU NPSF

.VUBCMF 7FDUPST
ƌ.PSJB .PSJB 8POEFS PG UIF /PSUIFSO XPSME 5PP
EFFQ XF EFMWFE UIFSF BOE XPLF UIF OBNFMFTT GFBSƍ
ƈ (M³JO 5IF 'FMMPXTIJQ PG UIF 3JOH

8IBU JG XF XBOU TPNFUIJOH FWFO GBTUFS "MUIPVHI NBOZ


QFPQMF EPOƊU SFBMJ[F UIJT BCPVU )BTLFMM XF DBO PCUBJO UIF CFOF
ƶUT PG JOQMBDF VQEBUFT JG XF TP EFTJSF 8IBU TFUT )BTLFMM BQBSU
JT UIBU XF DBOOPU EP TP JO B XBZ UIBU DPNQSPNJTFT SFGFSFOUJBM
USBOTQBSFODZ PS UIF OJDF FRVBUJPOBM QSPQFSUJFT PVS FYQSFTTJPOT
IBWF 'JSTU XFƊMM EFNPOTUSBUF IPX UP EP UIJT UIFO XFƊMM UBML
BCPVU IPX UIJT JT EFTJHOFE UP CFIBWF QSFEJDUBCMZ
)FSF DPNFT BO FYBNQMF

module Main where

import Control.Monad.Primitive
import Control.Monad.ST
import Criterion.Main
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as MV
import qualified Data.Vector.Generic.Mutable as GM
$)"15&3  #"4*$ -*#3"3*&4 

mutableUpdateIO :: Int -> IO (MV.MVector RealWorld Int)


mutableUpdateIO n = do
mvec <- GM.new (n+1)
go n mvec
where go 0 v = return v
go n v = (MV.write v n 0) >> go (n-1) v

mutableUpdateST :: Int -> V.Vector Int


mutableUpdateST n = runST $ do
mvec <- GM.new (n+1)
go n mvec
where go 0 v = V.freeze v
go n v = (MV.write v n 0) >> go (n-1) v

main :: IO ()
main = defaultMain
[ bench "mutable IO vector"
$ whnfIO (mutableUpdateIO 9998)
, bench "mutable ST vector"
$ whnf mutableUpdateST 9998
]

8FƊSF HPJOH UP UBML BCPVU runST TIPSUMZ 'PS UIF NPNFOU


MFUƊT DPODFOUSBUF PO UIF GBDU UIBU UIF NVUBCMF IO WFSTJPO JT
BQQSPYJNBUFMZ  Y GBTUFS UIBO UIF PSJHJOBM VOCBUDIFE MPPQ
JO PVS UFTUT 5IF 45 WFSTJPO JT BCPVU Y TMPXFS UIBO UIF IO
$)"15&3  #"4*$ -*#3"3*&4 

WFSTJPO CVU TUJMM WFSZ GBTU 5IF BEEFE UJNF JO UIF 45 WFSTJPO JT
GSPN GSFF[JOH UIF NVUBCMF WFDUPS JOUP BO PSEJOBSZ WFDUPS 8F
XPOƊU FYQMBJO 45 GVMMZ IFSF CVU BT XFƊMM TFF JU DBO CF IBOEZ
XIFO ZPV XBOU UP UFNQPSBSJMZ NBLF TPNFUIJOH NVUBCMF BOE
FOTVSF OP NVUBCMF SFGFSFODFT BSF FYQPTFE PVUTJEF PG UIF 45
NPOBE
)FSF XFSF UIF UJNJOHT XF HPU XJUI UIF WBSJPVT WFDUPS PQFS
BUJPOT PO PVS DPNQVUFS

7BSJBOU .JDSPTFDPOET
TMPX  
CBUDI-JTU 
CBUDI7FDUPS 
NVUBCMF6QEBUF45 
NVUBCMF6QEBUF*0 

/PUBCMZ NPTU PG UIF QFSGPSNBODF JNQSPWFNFOU XBT GSPN


OPU EPJOH TPNFUIJOH TJMMZ %POƊU SFTPSU UP UIF VTF PG NVUBUJPO
WJB *0 PS 45 FYDFQU XIFSF ZPV LOPX JUƊT OFDFTTBSZ *UƊT XPSUI
OPUJOH UIBU HJWFO PVS UFTU JOWPMWFE VQEBUJOH BMNPTU  
JOEJDFT JO UIF WFDUPS XF TQFOU BO BWFSBHF PG  OBOPTFDPOET
QFS VQEBUF XIFO XF VTFE NVUBCJMJUZ BOE  OT XIFO XF EJE
JU JO CBUDI XJUI B QFSTJTUFOU WFDUPS
$)"15&3  #"4*$ -*#3"3*&4 

" TJEFCBS PO UIF 45 .POBE


45 DBO CF UIPVHIU PG BT B NVUBCMF WBSJBOU PG UIF TUSJDU 4UBUF
NPOBE 'SPN BOPUIFS BOHMF JU DPVME CF UIPVHIU PG BT *0
SFTUSJDUFE FYDMVTJWFMZ UP NVUBUJPO XIJDI JT HVBSBOUFFE TBGF
4BGF IPX 45 JT SFMZJOH PO UIF QSJODJQMF CFIJOE UIBU PME
QIJMPTPQIJDBM TBX BCPVU UIF USFF UIBU GBMMT JO UIF GPSFTU XJUI OP
POF UP TFF JU GBMM 5IF JEFB CFIJOE UIJT ƌNPSBMMZ FƵFDUGSFFƍ VO
EFSTUBOEJOH PG NVUBCMF TUBUF XBT JOUSPEVDFE JO UIF QBQFS -B[Z
'VODUJPOBM 4UBUF 5ISFBET *U VOGSFF[FT ZPVS EBUB NVUBUFT
JU UIFO SFGSFF[FT JU TP UIBU JU DBOƊU NVUBUF BOZNPSF 5IVT JU
NBOBHFT UP NVUBUF BOE TUJMM NBJOUBJO SFGFSFOUJBM USBOTQBSFODZ
'PS 45 UP XPSL QSPQFSMZ UIF DPEF UIBU NVUBUFT UIF EBUB
NVTU OPU HFU SFPSEFSFE CZ UIF PQUJNJ[FS PS PUIFSXJTF NPO
LFZFE XJUI NVDI MJLF UIF DPEF JO *0 4P UIFSF NVTU CF TPNF
UIJOH VOEFSMZJOH UIF UZQF XIJDI QSFWFOUT ()$ SVJOJOH PVS
EBZ -FU VT FYBNJOF UIF 45 UZQF

Prelude> import Control.Monad.ST


Prelude> :info ST
type role ST nominal representational
newtype ST s a = GHC.ST.ST (GHC.ST.STRep s a)
...
Prelude> import GHC.ST
Prelude> :info STRep

-B[Z 'VODUJPOBM 4UBUF 5ISFBET +PIO -BVODICVSZ BOE 4JNPO 1FZUPO +POFT
$)"15&3  #"4*$ -*#3"3*&4 

type STRep s a =
GHC.Prim.State# s -> (# GHC.Prim.State# s, a #)

5IFSFƊT B CJU PG VHMJOFTT JO IFSF UIBU TIPVMEOƊU CF UPP TVS


QSJTJOH BǒFS ZPVƊWF TFFO ()$ $PSF JO UIF QSFWJPVT DIBQUFS
8IBUƊT JNQPSUBOU JT UIBU Ԣ JT HFUUJOH JUT UZQF GSPN UIF UIJOH
ZPVƊSF NVUBUJOH CVU JU IBT OP WBMVFMFWFM XJUOFTT 5IF 4UBUF
NPOBE IFSF JT UIFSFGPSF FSBTBCMF JU DBO FODBQTVMBUF UIJT NV
UBUJPO QSPDFTT BOE UIFO NFMU BXBZ
*UƊT JNQPSUBOU UP VOEFSTUBOE UIBU Ԣ JTOƊU UIF TUBUF ZPVƊSF
NVUBUJOH 5IF NVUBUJPO JT B TJEF FƵFDU PG IBWJOH FOUFSFE
UIF DMPTVSFT UIBU QFSGPSN UIF FƵFDU 5IJT TUSJDU VOMJǒFE TUBUF
USBOTGPSNFS NPOBE IBQQFOT UP TUSVDUVSF ZPVS DPEF JO B XBZ
UIBU QSFTFSWFT UIF JOUFOEFE PSEFS PG UIF DPNQVUBUJPOT BOE
UIFJS BTTPDJBUFE FƵFDUT
#Z DMPTVSFT IFSF XF NFBO MBNCEB FYQSFTTJPOT 0G DPVSTF
XF EP CFDBVTF UIJT XIPMF CPPL JT POF HJBOU MBNCEB FYQSFTTJPO
VOEFS UIF IPPE &OUFSJOH FBDI MBNCEB QFSGPSNT JUT FƵFDUT
5IF FƵFDUT PG B TFSJFT PG MBNCEBT BSF OPU CBUDIFE CFDBVTF UIF
PSEFSJOH JT JNQPSUBOU XIFO XFƊSF QFSGPSNJOH FƵFDUT BT FBDI
OFX FYQSFTTJPO NJHIU EFQFOE PO UIF FƵFDUT PG UIF QSFWJPVT
POF 5IF FƵFDUT BSF QFSGPSNFE BOE UIFO JG UIF WBMVF UIBU
TIPVME SFTVMU GSPN UIF DPNQVUBUJPO JT BMTP HPJOH UP CF VTFE
UIF WBMVF JT FWBMVBUFE
4P XIBU JT UIF Ԣ UZQF GPS 8FMM XIJMF JUƊT BMM XFMM BOE HPPE UP
BTL QPMJUFMZ UIBU QSPHSBNNFST GSFF[F B NVUBCMF SFGFSFODF JOUP
$)"15&3  #"4*$ -*#3"3*&4 

B QFSTJTUFOU JNNVUBCMF EBUB TUSVDUVSF BT UIF ƶOBM SFTVMUƒZPV


DBOƊU DPVOU PO UIBU 45 FOGPSDFT JU BU DPNQJMFUJNF CZ NBLJOH
JU TP UIBU Ԣ XJMM OFWFS VOJGZ XJUI BOZUIJOH PVUTJEF PG UIF 45
.POBE 5IF USJDL GPS UIJT JT DBMMFE FYJTUFOUJBM RVBOUJƶDBUJPO
CVU IBWJOH TBJE UIJT XPOƊU OFDFTTBSJMZ NFBO BOZUIJOH UP ZPV
SJHIU OPX #VU JU EPFT QSFWFOU ZPV BDDJEFOUBMMZ MFBLJOH NV
UBCMF SFGFSFODFT UP DPEF PVUTJEF 45 XIJDI DPVME UIFO MFBE UP
DPEF UIBU EPFT VOQSFEJDUBCMF UIJOHT EFQFOEJOH PO UIF TUBUF PG
UIF CJUT JO NFNPSZ
"WPJE EJQQJOH JO BOE PVU PG 45 PWFS BOE PWFS 5IF UIBXT
BOE GSFF[FT XJMM DPTU ZPV JO TJUVBUJPOT XIFSF JU NJHIU IBWF
CFFO CFUUFS UP KVTU VTF IO #BUDIJOH ZPVS NVUBUJPO JT CFTU GPS
QFSGPSNBODF BOE DPEF DPNQSFIFOTJCJMJUZ

&YFSDJTFT 7FDUPS
4FUVQ B CFODINBSL IBSOFTT XJUI $SJUFSJPO UP QSPƶMF IPX NVDI
NFNPSZ CPYFE BOE VOCPYFE WFDUPST DPOUBJOJOH UIF TBNF
EBUB VTFT :PV DBO DPNCJOF UIJT XJUI B CFODINBSL UP HJWF JU
TPNFUIJOH UP EP GPS B GFX TFDPOET 8FƊSF OPU HJWJOH ZPV B MPU
CFDBVTF ZPVƊSF HPJOH UP IBWF UP MFBSO UP SFBE EPDVNFOUBUJPO
BOE TPVSDF DPEF BOZXBZ

&YJTUFOUJBMMZ RVBOUJƶFE UZQFT )BTLFMM 8JLJCPPL
https://en.wikibooks.org/wiki/Haskell/Existentially_quantified_types
$)"15&3  #"4*$ -*#3"3*&4 

 4USJOH UZQFT


5IF UJUMF JT B TMJHIU CJU PG B NJTOPNFS BT XFƊMM BDUVBMMZ UBML
BCPVU UXP TUSJOH PS UFYU
UZQFT BOE POF UZQF GPS SFQSFTFOUJOH
TFRVFODFT PG CZUFT )FSFƊT B RVJDL SVOEPXO PO 4USJOH 5FYU
BOE #ZUF4USJOH

4USJOH
:PV LOPX XIBU 4USJOH JT *UƊT B UZQF BMJBT GPS B MJTU PG $IBS ZFU
VOEFSOFBUI JUƊT OPU RVJUF BT TJNQMF BT BO BDUVBM MJTU PG $IBS
0OF PG UIF CFOFƶUT PG VTJOH TUSJOHT JT UIF TJNQMJDJUZ BOE
UIFZƊSF FBTZ FOPVHI UP FYQMBJO 'PS NPTU EFNPOTUSBUJPO BOE
UPZ QSPHSBN QVSQPTFT UIFZƊSF KVTU ƶOF
)PXFWFS MJLF MJTUT UIFNTFMWFT UIFZ DBO CF JOƶOJUF 5IF
NFNPSZ VTBHF GPS FWFO WFSZ MBSHF TUSJOHT DBO HFU PVU PG DPOUSPM
SBQJEMZ 'VSUIFSNPSF UIFZ IBWF WFSZ JOFƸDJFOU DIBSBDUFSCZ
DIBSBDUFS JOEFYJOH JOUP UIF 4USJOH 5IF UJNF UBLFO UP EP B
MPPLVQ JODSFBTFT QSPQPSUJPOBUFMZ XJUI UIF MFOHUI PG UIF MJTU

5FYU
5IJT POF DPNFT JO UIF UFYU MJCSBSZ PO )BDLBHF 5IJT JT CFTU
XIFO ZPV IBWF QMBJO UFYU CVU OFFE UP TUPSF UIF EBUB NPSF
FƸDJFOUMZ ƈ QBSUJDVMBSMZ BT JU DPODFSOT NFNPSZ VTBHF

http://hackage.haskell.org/package/text
$)"15&3  #"4*$ -*#3"3*&4 

8FƊWF VTFE UIJT POF B CJU JO QSFWJPVT DIBQUFST XIFO XF


XFSF QMBZJOH XJUI 0WFSMPBEFE4USJOHT 5IF CFOFƶUT IFSF BSF
UIBU ZPV HFU

Ƒ DPNQBDU SFQSFTFOUBUJPO JO NFNPSZ BOE

Ƒ FƸDJFOU JOEFYJOH JOUP UIF TUSJOH

)PXFWFS 5FYU JT FODPEFE BT 65' BOE UIBU JTOƊU XIBU


NPTU QFPQMF FYQFDU HJWFO 65'ƊT QPQVMBSJUZ *O 5FYUƊT EF
GFOTF 65' JT PǒFO GBTUFS EVF UP DBDIF GSJFOEMJOFTT WJB
DIVOLJFS BOE NPSF QSFEJDUBCMF NFNPSZ BDDFTTFT

%POƊU USVTU ZPVS HVU NFBTVSF


8F NFOUJPOFE 5FYU IBT B NPSF DPNQBDU NFNPSZ SFQSFTFO
UBUJPO CVU XIBU EP ZPV UIJOL UIF NFNPSZ QSPƶMF GPS UIF
GPMMPXJOH QSPHSBN XJMM MPPL VQ )JHI ƶSTU UIFO MPX PS MPX
ƶSTU UIFO IJHI
$)"15&3  #"4*$ -*#3"3*&4 

module Main where

import Control.Monad
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import qualified System.IO as SIO

-- replace "/usr/share/dict/words" as appropriate


dictWords :: IO String
dictWords = SIO.readFile "/usr/share/dict/words"

dictWordsT :: IO T.Text
dictWordsT = TIO.readFile "/usr/share/dict/words"

main :: IO ()
main = do
replicateM_ 10 (dictWords >>= print)
replicateM_ 10 (dictWordsT >>= TIO.putStrLn)

5IF JTTVF JT UIBU 5FYU XFOU BIFBE BOE MPBEFE UIF FOUJSF ƶMF
JOUP NFNPSZ FBDI PG UIF UFO UJNFT ZPV GPSDFE UIF *0 BDUJPO
5IF readFile PQFSBUJPO GPS 4USJOH IPXFWFS XBT MB[Z BOE POMZ
SFBE BT NVDI PG UIF ƶMF JOUP NFNPSZ BT OFFEFE UP QSJOU UIF
EBUB UP stdout 5IF QSPQFS XBZ UP IBOEMF JODSFNFOUBMMZ QSP
$)"15&3  #"4*$ -*#3"3*&4 

DFTTJOH EBUB JT XJUI TUSFBNJOH CVU UIJT JT OPU TPNFUIJOH XFƊMM


DPWFS JO EFUBJM JO UIJT CPPL )PXFWFS UIFSF JT B MB[Z XBZ XF
DPVME DIBOHF UIJT

-- Add the following to the module you


-- already made for profiling String and Text.
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.IO as TLIO

dictWordsTL :: IO TL.Text
dictWordsTL = TLIO.readFile "/usr/share/dict/words"

main :: IO ()
main = do
replicateM_ 10 (dictWords >>= print)
replicateM_ 10 (dictWordsT >>= TIO.putStrLn)
replicateM_ 10 (dictWordsTL >>= TLIO.putStrLn)

/PX ZPV TIPVME TFF NFNPSZ VTBHF QMVNNFU BHBJO BǒFS


B NJEEMF QMBUFBV CFDBVTF ZPVƊSF SFBEJOH JO BT NVDI UFYU BT
OFDFTTBSZ UP QSJOU BCMF UP EFBMMPDBUF BT ZPV HP 5IJT JT TPNF
CVU OPU BMM PG UIF CFOFƶUT PG TUSFBNJOH CVU XF EP TUSPOHMZ
SFDPNNFOE VTJOH TUSFBNJOH SBUIFS UIBO SFMZJOH PO B MB[Z *0
"1*

https://wiki.haskell.org/Pipes

)VF IVF IVF
$)"15&3  #"4*$ -*#3"3*&4 

#ZUF4USJOH
5IJT JT OPU BDUVBMMZ B TUSJOH 0S UFYU /PU OFDFTTBSJMZ BOZXBZ
#ZUF4USJOHT BSF TFRVFODF PG CZUFT SFQSFTFOUFE JOEJSFDUMZ
BT
B WFDUPS PG 8PSE WBMVFT 5FYU PO B DPNQVUFS JT NBEF VQ PG
CZUFT CVU JU IBT UP IBWF B QBSUJDVMBS FODPEJOH JO PSEFS GPS JU
UP CF UFYU &ODPEJOHT PG UFYU DBO CF "4$** 65' 65'
PS 65' VTVBMMZ 65' PS 65' 5IF 5FYU UZQF FODPEFT
UIF EBUB BT 65' QBSUMZ GPS QFSGPSNBODF *UƊT PǒFO GBTUFS
UP SFBE MBSHFS DIVOLT PG EBUB BU B UJNF GSPN NFNPSZ TP UIF
CJUTQFSSVOF FODPEJOH PG 65' QFSGPSNT B CJU CFUUFS JO
NPTU DBTFT
5IF NBJO CFOFƶU PG #ZUF4USJOH JT UIBU JUƊT FBTZ UP VTF WJB UIF
0WFSMPBEFE4USJOHT QSBHNB CVU JT CZUFT JOTUFBE PG UFYU 5IJT
BEESFTTFT B MBSHFS QSPCMFN TQBDF UIBO NFSF UFYU
5IF ƷJQ TJEF PG UIBU PG DPVSTF JT UIBU JU FODPNQBTTFT CZUF
EBUB UIBU JTOƊU DPNQSFIFOTJCMF UFYU 5IBUƊT B ESBXCBDL JG ZPV
EJEOƊU NFBO UP QFSNJU OPOUFYU CZUF TFRVFODFT JO ZPVS EBUB

#ZUF4USJOH FYBNQMFT

)FSFƊT BO FYBNQMF IJHIMJHIUJOH UIBU #ZUF4USJOHT BSF OPU BMXBZT


UFYU
$)"15&3  #"4*$ -*#3"3*&4 

{-# LANGUAGE OverloadedStrings #-}

module BS where

import qualified Data.Text.IO as TIO


import qualified Data.Text.Encoding as TE
import qualified Data.ByteString.Lazy as BL
-- https://hackage.haskell.org/package/zlib
import qualified Codec.Compression.GZip as GZip

8FƊSF HPJOH UP VTF UIF gzip DPNQSFTTJPO GPSNBU UP DPNQSFTT


TPNF EBUB 5IJT JT TP XF IBWF BO FYBNQMF PG EBUB UIBU JODMVEFT
CZUFT UIBU BSFOƊU B WBMJE UFYU FODPEJOH

input :: BL.ByteString
input = "123"

compressed :: BL.ByteString
compressed = GZip.compress input

5IF (;JQ NPEVMF FYQFDUT B MB[Z CZUFTUSJOH QSPCBCMZ TP


UIBU JUƊT TUSFBNJOH GSJFOEMZ
$)"15&3  #"4*$ -*#3"3*&4 

main :: IO ()
main = do
TIO.putStrLn $ TE.decodeUtf8 (s input)
TIO.putStrLn $ TE.decodeUtf8 (s compressed)
where s = BL.toStrict

5IF FODPEJOH NPEVMF JO UIF UFYU MJCSBSZ FYQFDUT TUSJDU CZUFTUSJOHT


TP XF IBWF UP NBLF UIFN TUSJDU CFGPSF BUUFNQUJOH B EFDPEJOH
5IF TFDPOE UFYU EFDPEF XJMM GBJM CFDBVTF UIFSFƊMM CF B CZUF UIBU
JTOƊU SFDPHOJ[BCMZ DPSSFDU BT BO FODPEJOH PG UFYU JOGPSNBUJPO

#ZUF4USJOH USBQT

:PV NJHIU UIJOL UP ZPVSTFMG BU TPNF QPJOU ƌ*ƊE MJLF UP DPOWFSU B


4USJOH UP B #ZUF4USJOHƍ 5IJT JT B QFSGFDUMZ SFBTPOBCMF UIJOH UP
XBOU UP EP CVU NBOZ )BTLFMMFST XJMM NJTUBLFOMZ VTF UIF $IBS
NPEVMF JO UIF #ZUF4USJOH MJCSBSZ XIFO UIBU JT OPU SFBMMZ XIBU
UIFZ XBOU 5IF $IBS NPEVMF JT SFBMMZ B DPOWFOJFODF GPS EBUB
UIBU NJOHMFT CZUFT BOE "4$** EBUB UIFSF *U EPFTOƊU XPSL GPS
6OJDPEF BOE TIPVMEOƊU CF VTFE BOZXIFSF UIFSFƊT FWFO B IJOU
PG QPTTJCJMJUZ UIBU UIFSF DPVME CF 6OJDPEF EBUB 'PS FYBNQMF

4JODF "4$** JT  CJUT BOE $IBS JT  CJUT ZPV DPVME VTF UIF FJHIUI CJU UP SFQSFTFOU
-BUJO DIBSBDUFST )PXFWFS TJODF ZPV XJMM VTVBMMZ JOUFOE UP DPOWFSU UIF $IBS EBUB UP
FODPEJOHT MJLF 65' BOE 65' XIJDI VTF UIF FJHIUI CJU EJƵFSFOUMZ UIBU XPVME CF
VOXJTF
$)"15&3  #"4*$ -*#3"3*&4 

module Char8ProllyNotWhatYouWant where

import qualified Data.Text as T


import qualified Data.Text.Encoding as TE
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
-- utf8-string
import qualified Data.ByteString.UTF8 as UTF8

-- Manual unicode encoding of Japanese text


-- GHC Haskell allows UTF8 in source files
s :: String
s = "\12371\12435\12395\12385\12399\12289\
\20803\27671\12391\12377\12363\65311"

utf8ThenPrint :: B.ByteString -> IO ()


utf8ThenPrint =
putStrLn . T.unpack . TE.decodeUtf8

throwsException :: IO ()
throwsException =
utf8ThenPrint (B8.pack s)

bytesByWayOfText :: B.ByteString
bytesByWayOfText = TE.encodeUtf8 (T.pack s)
$)"15&3  #"4*$ -*#3"3*&4 

-- letting utf8-string do it for us


libraryDoesTheWork :: B.ByteString
libraryDoesTheWork = UTF8.fromString s

thisWorks :: IO ()
thisWorks = utf8ThenPrint bytesByWayOfText

alsoWorks :: IO ()
alsoWorks = utf8ThenPrint libraryDoesTheWork

5IFO XF HP UP SVO UIF DPEF UIBU BUUFNQUT UP HFU B #ZUF4USJOH


WJB UIF $IBS NPEVMF XIJDI DPOUBJOT 6OJDPEF

Prelude> throwsException
*** Exception: Cannot decode byte '\x93':
Data.Text.Internal.Encoding.decodeUtf8:
Invalid UTF-8 stream

:PV DBO VTF ord GSPN %BUB$IBS UP HFU UIF *OU WBMVF PG UIF
CZUF PG B DIBSBDUFS

Prelude> import Data.Char (ord)


Prelude> :t ord
ord :: Char -> Int
Prelude> ord 'A'
65
Prelude> ord '\12435'
$)"15&3  #"4*$ -*#3"3*&4 

12435

5IF TFDPOE FYBNQMF TFFNT PCWJPVT CVU XIFO UIF EBUB JT


SFQSFTFOUFE OBUJWFMZ PO ZPVS DPNQVUFS UIJT JT NPSF VTFGVM
6TF OPO&OHMJTI XFCTJUFT UP HFU TBNQMF EBUB UP UFTU
8F DBO OPX VTF UIF PSEFSJOH PG DIBSBDUFST UP ƶOE UIF ƶSTU
DIBSBDUFS UIBU CSFBLT $IBS

Prelude> let charSequence = map (:[]) ['A'..'']


Prelude> mapM_ (utf8ThenPrint . B8.pack) charSequence
... bunch of output ...

5IFO UP OBSSPX UIJT EPXO XF LOPX XF OFFE UP ƶOE XIBU


DBNF BǒFS UIF UJMEF BOE UIF \DEL DIBSBDUFS

... some trial and error ...


Prelude> mapM_ putStrLn (take 3 $ drop 60 charSequence)
}
~

)SN PLBZ CVU XIFSF JT UIJT JO UIF "4$** UBCMF 8F DBO


VTF UIF PQQPTJUF PG UIF ord GVODUJPO GSPN %BUB$IBS chr UP
EFUFSNJOF UIJT

Prelude> import Data.Char (chr)


Prelude> :t chr
chr :: Int -> Char
$)"15&3  #"4*$ -*#3"3*&4 

Prelude> map chr [0..128]


... prints the first 129 characters ...

8IBU JU QSJOUFE DPSSFTQPOET UP UIF "4$** UBCMF XIJDI JT


IPX 65' SFQSFTFOUT UIF TBNF DIBSBDUFST /PX XF DBO VTF
UIJT GVODUJPO UP OBSSPX EPXO QSFDJTFMZ XIBU PVS DPEF GBJMT BU

-- works fine
Prelude> utf8ThenPrint (B8.pack [chr 127])

-- fails
Prelude> utf8ThenPrint (B8.pack [chr 128])
*** Exception: Cannot decode byte '\x80':
Data.Text.Internal.Encoding.decodeUtf8:
Invalid UTF-8 stream

4P EPOƊU EP UIJT 5IJT QSPCMFN JTOƊU FYDMVTJWF UP )BTLFMM ƈ


BMM QSPHSBNNJOH MBOHVBHFT NVTU BDLOPXMFEHF UIF FYJTUFODF
PG EJƵFSFOU FODPEJOHT GPS UFYU

$IBS JT CBE NNNNNLBZ 5IF $IBS NPEVMF JT OPU GPS 6OJ


DPEF PS GPS UFYU NPSF HFOFSBMMZ 5IF QBDL GVODUJPO JU DPOUBJOT
JT GPS "4$** EBUB POMZ 5IJT GPPMT QSPHSBNNFST CFDBVTF UIF
65' FODPEJOH PG UIF &OHMJTI BMQIBCFU XJUI TPNF -BUJO FY
UFOTJPO DIBSBDUFST JOUFOUJPOBMMZ PWFSMBQT FYBDUMZ XJUI UIF TBNF

https://en.wikipedia.org/wiki/ASCII
$)"15&3  #"4*$ -*#3"3*&4 

CZUFT "4$** VTFT UP FODPEF UIPTF DIBSBDUFST 4P UIF GPMMPXJOH


XJMM XPSL CVU JT XSPOH JO QSJODJQMF

Prelude> utf8ThenPrint (B8.pack "blah")


blah

(FUUJOH B 65' CZUFTUSJOH WJB UIF UFYU PS VUGTUSJOH MJ


CSBSJFT XPSLT ƶOF BT ZPVƊMM TFF JG ZPV UBLF B MPPL BU UIF SFTVMU
PG thisWorks BOE alsoWorks

8IFO XPVME * VTF #ZUF4USJOH JOTUFBE PG 5FYU GPS


UFYUVBM EBUB
5IJT EPFT IBQQFO TPNFUJNFT VTVBMMZ CFDBVTF ZPV XBOU UP
LFFQ EBUB UIBU BSSJWFE JO B 65' FODPEJOH JO 65' 0G
UFO UIJT IBQQFOT CFDBVTF ZPV SFBE 65' EBUB GSPN B ƶMF PS
OFUXPSL TPDLFU BOE ZPV EPOƊU XBOU UIF PWFSIFBE PG CPVODJOH
JU JOUP BOE CBDL PVU PG 5FYU *G ZPV EP UIJT ZPV NJHIU XBOU
UP VTF OFXUZQFT UP BWPJE BDDJEFOUBMMZ NJYJOH UIJT EBUB XJUI
OPO65' CZUFTUSJOHT

 $IBQUFS &YFSDJTFT


%JƵFSFODF -JTU
-JTUT BSF SFBMMZ OJDF CVU UIFZ EPOƊU BQQFOE PS DPODBUFOBUF
DIFBQMZ 8F DPWFSFE 4FRVFODF BT POF QPUFOUJBM TPMVUJPO UP
$)"15&3  #"4*$ -*#3"3*&4 

UIJT CVU UIFSFƊT BDUVBMMZ B TJNQMFS EBUB TUSVDUVSF UIBU TPMWFT


TMPX BQQFOEJOH TQFDJƶDBMMZ UIF EJƵFSFODF MJTU
3BUIFS UIBO KVTUJGZ BOE FYQMBJO EJƵFSFODF MJTUT QBSU PG UIF
FYFSDJTF JT ƶHVSJOH PVU XIBU JU EPFT BOE XIZ "UUFNQU UIF FY
FSDJTF CFGPSF SFTPSUJOH UP UIF UVUPSJBM JO UIF GPMMPXVQ SFBEJOH
'JSTU UIF %-JTU UZQF JT CVJMU PO UPQ PG PSEJOBSZ MJTUT CVU JUƊT B
GVODUJPO

newtype DList a = DL { unDL :: [a] -> [a] }

5IF "1* UIBU GPMMPXT JT CBTFE PO DPEF CZ %PO 4UFXBSU BOE


4FBO -FBUIFS )FSFƊT XIBU ZPV OFFE UP XSJUF

 empty :: DList a
empty = undefined
{-# INLINE empty #-}

 singleton :: a -> DList a


singleton = undefined
{-# INLINE singleton #-}

 toList :: DList a -> [a]


toList = undefined
{-# INLINE toList #-}
$)"15&3  #"4*$ -*#3"3*&4 

 -- Prepend a single element to a dlist.


infixr `cons`
cons :: a -> DList a -> DList a
cons x xs = DL ((x:) . unDL xs)
{-# INLINE cons #-}

 -- Append a single element to a dlist.


infixl `snoc`
snoc :: DList a -> a -> DList a
snoc = undefined
{-# INLINE snoc #-}

 -- Append dlists.
append :: DList a -> DList a -> DList a
append = undefined
{-# INLINE append #-}

8IBUƊT TP OJǒZ BCPVU %-JTUT JT UIBU DPOT TOPD BOE BQQFOE


BMM UBLF UIF TBNF BNPVOU PG UJNF OP NBUUFS IPX MPOH UIF EMJTU
JT 5IBU JT UP TBZ UIFZ UBLF B DPOTUBOU BNPVOU PG UJNF SBUIFS
UIBO HSPXJOH XJUI UIF TJ[F PG UIF EBUB TUSVDUVSF
:PVS HPBM JT UP HFU UIF GPMMPXJOH CFODINBSL IBSOFTT SVOOJOH
XJUI UIF QFSGPSNBODF FYQFDUFE
$)"15&3  #"4*$ -*#3"3*&4 

schlemiel :: Int -> [Int]


schlemiel i = go i []
where go 0 xs = xs
go n xs = go (n-1) ([n] ++ xs)

constructDlist :: Int -> [Int]


constructDlist i = toList $ go i empty
where go 0 xs = xs
go n xs = go (n-1) (singleton n `append` xs)

main :: IO ()
main = defaultMain
[ bench "concat list" $ whnf schlemiel 123456
, bench "concat dlist" $ whnf constructDlist 123456
]

*G ZPV SVO UIF BCPWF UIF %-JTU WBSJBOU TIPVME CF BCPVU


UXJDF BT GBTU

" TJNQMF RVFVF


8FƊSF HPJOH UP XSJUF BOPUIFS EBUB TUSVDUVSF JO UFSNT PG MJTU CVU
UIJT UJNF JUƊMM CF B RVFVF 5IF NBJO GFBUVSF PG RVFVFT JT UIBU
XF DBO BEE FMFNFOUT UP UIF GSPOU DIFBQMZ BOE UBLF JUFNT PƵ
UIF CBDL PG UIF RVFVF DIFBQMZ
$)"15&3  #"4*$ -*#3"3*&4 

-- From Okasaki's Purely Functional Data Structures


data Queue a =
Queue { enqueue :: [a]
, dequeue :: [a]
} deriving (Eq, Show)

-- adds an item
push :: a -> Queue a -> Queue a
push = undefined

pop :: Queue a -> Maybe (a, Queue a)


pop = undefined

8FƊSF HPJOH UP HJWF ZPV MFTT DPEF UIJT UJNF CVU ZPVS UBTL JT
UP JNQMFNFOU UIF BCPWF BOE XSJUF B CFODINBSL DPNQBSJOH JU
BHBJOTU QFSGPSNJOH BMUFSOBUJOH QVTIFT BOE QPQT GSPN B RVFVF
CBTFE PO B TJOHMF MJTU "MUFSOBUJOH TP UIBU ZPV DBOƊU UBLF BEWBO
UBHF PG SFWFSTJOH UIF MJTU BǒFS B MPOH TFSJFT PG QVTIFT JO PSEFS
UP QFSGPSN B MPOH TFSJFT PG QPQT FƸDJFOUMZ
%POƊU GPSHFU UP IBOEMF UIF DBTF XIFSF UIF EFRVFVF JT FNQUZ
BOE ZPV OFFE UP TIJǒ JUFNT GSPN UIF FORVFVF UP UIF EFRVFVF
:PV OFFE UP EP TP XJUIPVU WJPMBUJOH ƌƶSTU DPNF ƶSTU TFSWFEƍ
-BTUMZ CFODINBSL JU BHBJOTU 4FRVFODF $PNF VQ XJUI B
WBSJFUZ PG UFTUT "EE BEEJUJPOBM PQFSBUJPOT GPS ZPVS 2VFVF
UZQF JG ZPV XBOU
$)"15&3  #"4*$ -*#3"3*&4 

 'PMMPXVQ SFTPVSDFT


 $SJUFSJPO UVUPSJBM #SZBO 0Ɗ4VMMJWBO
http://www.serpentine.com/criterion/tutorial.html

 %FNZTUJGZJOH %-JTU 5PN &MMJT


http://h2.jaguarpaw.co.uk/posts/demystifying-dlist/

 .FNPSZ .BOBHFNFOU ()$ )BTLFMM 8JLJ


https://wiki.haskell.org/GHC/Memory_Management

 1FSGPSNBODF )BTLFMM 8JLJ


https://wiki.haskell.org/Performance

 1SBHNBT TQFDJƶDBMMZ UNPACK ()$ %PDVNFOUBUJPO

 )JHI 1FSGPSNBODF )BTLFMM +PIBO 5JCFMM


http://johantibell.com/files/slides.pdf

 )BTLFMM 1FSGPSNBODF 1BUUFSOT +PIBO 5JCFMM

 'BTUFS QFSTJTUFOU EBUB TUSVDUVSFT UISPVHI IBTIJOH +PIBO


5JCFMM

 -B[Z 'VODUJPOBM 4UBUF 5ISFBET +PIO -BVODICVSZ BOE


4JNPO 1FZUPO +POFT

 8SJUF )BTLFMM BT GBTU BT $ FYQMPJUJOH TUSJDUOFTT MB[JOFTT


BOE SFDVSTJPO %PO 4UFXBSU
$)"15&3  #"4*$ -*#3"3*&4 

 )BTLFMM BT GBTU BT $ " DBTF TUVEZ +BO 4UPMBSFL

 )BTLFMM ''5  0QUJNJTBUJPO 1BSU  *BO 3PTT

 6OEFSTUBOEJOH UIF 3FBM8PSME &ETLP EF 7SJFT

 4USFBN 'VTJPO %VODBO $PVUUT


http://code.haskell.org/~dons/papers/icfp088-coutts.pdf

 1VSFMZ GVODUJPOBM EBUB TUSVDUVSFT $ISJT 0LBTBLJ


$IBQUFS 

*0

*O UIPTF EBZT NBOZ


TVDDFTTGVM QSPKFDUT TUBSUFE
PVU BT HSBƸUJT PO B CFFS
NBU JO B WFSZ WFSZ TNPLZ
QVC

1FUFS + -BOEJO


$)"15&3  *0 

 *0
:PV TIPVME CF QSPVE PG ZPVSTFMG GPS NBLJOH JU UIJT GBS JOUP UIF
CPPL :PVƊSF KVHHMJOH NPOBET :PVƊWF EFGFBUFE BO BSNZ PG
NPOBE USBOTGPSNFST :PVƊSF DPNGPSUBCMF XJUI VTJOH BMHFCSBJD
TUSVDUVSFT JO UZQFDMBTT GPSN :PVƊWF HPU B SFBTPOBCMF JG DBTVBM
HSBTQ PG HSBQI SFEVDUJPO OPOTUSJDUOFTT BOE TIBSJOH 8JUI
UIPTF UIJOHT JO IBOE MFUƊT UBML BCPVU *0
8FƊWF VTFE UIF *0 UZQF BU WBSJPVT UJNFT UISPVHIPVU UIF
CPPL XJUI POMZ DVSTPSZ FYQMBOBUJPO :PV OP EPVCU LOPX UIBU
XF VTF UIJT UZQF JO )BTLFMM BT B NFBOT PG LFFQJOH PVS DIPDPMBUF
TFQBSBUF GSPN PVS QFBOVU CVUUFS ƈ UIBU JT PVS QVSF GVODUJPOT
GSPN PVS FƵFDUGVM POFT 1FSIBQT ZPVƊSF XPOEFSJOH IPX JU BMM
XPSLT XIBUƊT VOEFSOFBUI UIBU PQBRVF UZQF 5P NBOZ QFPQMF
*0 TFFNT NZTUFSJPVT
.PTU FYQMBOBUJPOT PG UIF *0 UZQF JO )BTLFMM EPOƊU IFMQ NVDI
FJUIFS 5IFZ TFFN EFTJHOFE UP DPOGVTF UIF SFBEFS SBUIFS UIBO
DPOWFZ BOZUIJOH VTFGVM %POƊU MPPL OPX CVU TPNFCPEZ JT XSJU
JOH BO FYQMBOBUJPO PG *0 SJHIU OPX UIBU VTFT WBO -BBSIPWFO
'SFF .POBET BOE DPTUBUF DPNPOBE DPBMHFCSBT UP FYQMBJO TPNF
UIJOH UIBUƊT NVDI TJNQMFS UIBO FJUIFS PG UIPTF UPQJDT
8FƊSF OPU HPJOH UP EP UIBU IFSF 8F XJMM JOTUFBE USZ UP
EFNZTUJGZ *0 B CJU 5IF JNQPSUBOU UIJOH BCPVU *0 JT UIBU JUƊT B
TQFDJBM LJOE PG EBUBUZQF UIBU JOIFSFOUMZ EJTBMMPXT DFSUBJO UZQFT
PG TIBSJOH UIVT QSFWFOUJOH UIF FƵFDUT PG UIPTF GVODUJPOT GSPN
QFSDPMBUJOH UISPVHIPVU ZPVS QSPHSBN :PV HPU B UBTUF PG UIJT
$)"15&3  *0 

XJUI PVS TIPSU JOUSPEVDUJPO UP UIF 45 UZQF JO UIF QSFWJPVT


DIBQUFS
*O UIJT DIBQUFS XF XJMM

Ƒ FYQMBJO IPX *0 XPSLT PQFSBUJPOBMMZ

Ƒ FYQMPSF XIBU JU TIPVME NFBO UP ZPV XIFO ZPV SFBE B UZQF


UIBU IBT *0 JO JU

Ƒ QSPWJEF B CJU NPSF EFUBJM BCPVU UIF *0 'VODUPS "QQMJDB


UJWF BOE .POBE

 8IFSF *0 FYQMBOBUJPOT HP BTUSBZ


" MPU PG FYQMBOBUJPOT PG *0 BSF NJTMFBEJOH PS NVEEMFE 8FƊWF
BMSFBEZ BMMVEFE UP UIF PWFSXSPVHIU BOE DPNQMFY FYQMBOBUJPOT
PG *0 0UIFST DBMM JU ƌUIF *0 .POBEƍ BOE TFFN UP FRVBUF *0
XJUI .POBE 8IJMF *0 JT B UZQF UIBU IBT B .POBE JOTUBODF JU
JT OPU POMZ B .POBE BOE NPOBET BSF OPU POMZ *0 4UJMM PUIFS
QSFTFOUBUJPOT JNQMZ UIBU PODF ZPV FOUFS *0 ZPV EFTUSPZ QV
SJUZ BOE SFGFSFOUJBM USBOTQBSFODZ "OE TPNF SFGFSFODFT EPOƊU
CPUIFS UP TBZ NVDI BCPVU *0 CFDBVTF UIF GBDU UIBU JU SFNBJOT
PQBRVF XPOƊU TUPQ ZPV GSPN EPJOH NPTU PG XIBU ZPV XBOU UP
VTF JU GPS BOZXBZ
8F XBOU UP PƵFS TPNF HVJEBODF JO DSJUJDBMMZ FWBMVBUJOH
FYQMBOBUJPOT PG *0 -FU VT DPOTJEFS POF PG UIF NPTU QPQVMBS
$)"15&3  *0 

FYQMBOBUJPOT PG *0 UIF POF UIBU BUUFNQUT UP FYQMBJO *0 JO


UFSNT PG 4UBUF

#VSO UIF 4UBUF UP UIF HSPVOE


5IF UFNQUBUJPO UP VTF 4UBUF UP HFU TPNFPOF DPNGPSUBCMF XJUI
UIF JEFB PG *0 JT TUSPOH (JWF UIF GPMMPXJOH QBTTBHF FBSMZ JO
UIF EPDVNFOUBUJPO UP GHC.IO B HBOEFS

5IF *0 .POBE JT KVTU BO JOTUBODF PG UIF 45 NPOBE


XIFSF UIF TUBUF JT UIF SFBM XPSME

5IF NPUJWBUJPO GPS UIFTF FYQMBOBUJPOT JT FBTZ UP VOEFSTUBOE


XIFO ZPV MPPL BU UIF VOEFSMZJOH UZQFT

-- from ghc-prim
import GHC.Prim
import GHC.Types

newtype State s a
= State {runState :: s -> (a, s)}

-- :info IO
newtype IO a =
IO (State# RealWorld
-> (# State# RealWorld, a #))
$)"15&3  *0 

:FQ JU TVSF MPPLT MJLF 4UBUF )PXFWFS UIJT JT MFTT NFBOJOHGVM


PS IFMQGVM UIBO ZPVƊE UIJOL BU ƶSTU
5IF JTTVF XJUI UIJT FYQMBOBUJPO JT UIBU ZPV EPOƊU VTFGVMMZ
TFF PS JOUFSBDU XJUI UIF VOEFSMZJOH 4UBUF JO *0 *UƊT OPU 4UBUF
JO UIF TFOTF UIBU POF VTFT 4UBUF 4UBUF5 PS FWFO 45 BMUIPVHI
UIF CFIBWJPS PG UIF Ԣ IFSF JT DFSUBJOMZ WFSZ MJLF UIBU PG 45
5IF 4UBUF IFSF JT B TJHOBMMJOH NFDIBOJTN GPS UFMMJOH ()$
XIBU PSEFS ZPVS *0 BDUJPOT BSF JO BOE XIBU B VOJRVF *0 BDUJPO
JT *G XF MPPL UISPVHI UIF ()$1SJN EPDVNFOUBUJPO XF TFF

4UBUF JT UIF QSJNJUJWF VOMJǒFE UZQF PG TUBUFT *U IBT


POF UZQF QBSBNFUFS UIVT 4UBUF 3FBM8PSME PS 4UBUF
Ԣ XIFSF Ԣ JT B UZQF WBSJBCMF 5IF POMZ QVSQPTF PG
UIF UZQF QBSBNFUFS JT UP LFFQ EJƵFSFOU TUBUF UISFBET
TFQBSBUF *U JT SFQSFTFOUFE CZ OPUIJOH BU BMM
3FBM8PSME JT EFFQMZ NBHJDBM *U JT QSJNJUJWF CVU JU
JT OPU VOMJǒFE IFODF QUS"SH
 8F OFWFS NBOJQVMBUF
WBMVFT PG UZQF 3FBM8PSME JUƊT POMZ VTFE JO UIF UZQF
TZTUFN UP QBSBNFUFSJTF 4UBUF

8IFO UIFZ TBZ UIBU 3FBM8PSME JT ƌSFQSFTFOUFE CZ OPUIJOH


BU BMM ƍ UIFZ NFBO JU MJUFSBMMZ VTFT [FSP CJUT PG NFNPSZ 5IF
TUBUF UPLFOT VOEFSMZJOH UIF *0 UZQF BSF FSBTFE EVSJOH DPNQJMF
UJNF BOE TP BEE OP PWFSIFBE UP ZPVS SVOUJNF 4P UIF QSPCMFN
XJUI FYQMBJOJOH *0 JO UFSNT PG 4UBUF JT OPU QSFDJTFMZ UIBU JUƊT
XSPOH JUƊT UIBU JUƊT OPU B 4UBUF ZPV DBO NFBOJOHGVMMZ JOUFSBDU
$)"15&3  *0 

XJUI PS DPOUSPM JO UIF XBZ ZPVƊE FYQFDU GSPN UIF PUIFS 4UBUF
UZQFT

 5IF SFBTPO XF OFFE UIJT UZQF


4P MFUƊT USZ UP NPWF GSPN UIFSF UP BO VOEFSTUBOEJOH PG *0 UIBU
JT NFBOJOHGVM UP VT JO PVS EBZUPEBZ )BTLFMMJOH *0 QSJNBSJMZ
FYJTUT UP HJWF VT B XBZ UP PSEFS PQFSBUJPOT BOE UP EJTBCMF TPNF
PG UIF TIBSJOH UIBU XF UBMLFE TP NVDI BCPVU JO UIF DIBQUFS PO
OPOTUSJDUOFTT
()$ JT PSEJOBSJMZ GSFF UP EP B MPU PG SFPSEFSJOH PG PQFSB
UJPOT EFMBZJOH PG FWBMVBUJPO TIBSJOH PG OBNFE WBMVFT EVQMJ
DBUJOH DPEF WJB JOMJOJOH BOE PUIFS PQUJNJ[BUJPOT JO PSEFS UP
JODSFBTF QFSGPSNBODF 5IF NBJO UIJOH UIF *0 UZQF EPFT JT
UVSO PƵ NPTU PG UIPTF BCJMJUJFT

8IBU
/P SFBMMZ 5IBUƊT B MPU PG JU

0SEFS BOE DIBPT


"T XFƊWF TFFO JO UIF QSFWJPVT DIBQUFST ()$ DBO OPSNBMMZ
SFPSEFS PQFSBUJPOT 5IJT JT EJTBCMFE JO *0 BT JO 45
 *0 BDUJPOT
BSF JOTUFBE FODMPTFE XJUIJO OFTUFE MBNCEBT ƈ OFTUJOH JT UIF
POMZ XBZ UP FOTVSF UIBU BDUJPOT BSF TFRVFODFE XJUIJO B QVSF
MBNCEB DBMDVMVT
$)"15&3  *0 

/FTUJOH MBNCEBT JT IPX XF HVBSBOUFF UIBU UIJT

main = do
putStr "1"
putStr "2"
putStrLn "3"

XJMM PVUQVU ƌƍ BOE XF XBOU UIBU HVBSBOUFF 5IF VOEFSMZ


JOH SFQSFTFOUBUJPO PG *0 BMMPXT UIF BDUJPOT UP CF OFTUFE BOE
UIFSFGPSF TFRVFODFE
8IFO XF FOUFS B MBNCEB FYQSFTTJPO BOZ FƵFDUT UIBU OFFE UP
CF QFSGPSNFE XJMM CF QFSGPSNFE ƶSTU CFGPSF BOZ DPNQVUBUJPOT
BSF FWBMVBUFE 5IFO JG UIFSF JT B DPNQVUBUJPO UP FWBMVBUF UIBU
NBZ CF FWBMVBUFE OFYU CFGPSF XF FOUFS UIF OFYU MBNCEB UP
QFSGPSN UIF OFYU FƵFDU BOE TP PO 8FƊWF TFFO IPX UIJT QMBZT
PVU JO QSFWJPVT DIBQUFST UIJOL PG UIF QBSTFST UIBU QFSGPSN UIF
FƵFDU PG NPWJOH B ƌDVSTPSƍ UISPVHI UIF UFYU XJUIPVU SFEVDJOH
UP BOZ WBMVF BMTP SFDBMM XIBU XF TBX XJUI 45 BOE NVUBCMF
WFDUPST
*O GBDU UIF SFBTPO XF IBWF .POBE JT CFDBVTF JU XBT B NFBOT
PG BCTUSBDUJOH BXBZ UIF OFTUFE MBNCEB OPJTF UIBU VOEFSMJFT *0

 4IBSJOH
*O BEEJUJPO UP FOGPSDJOH PSEFSJOH *0 UVSOT PƵ B MPU PG UIF TIBS
JOH XF UBMLFE BCPVU JO UIF OPOTUSJDUOFTT DIBQUFS "T XFƊMM TPPO
$)"15&3  *0 

TFF JU EPFTOƊU EJTBCMF BMM GPSNT PG TIBSJOH ƈ JU DPVMEOƊU CFDBVTF


BMM )BTLFMM QSPHSBNT IBWF B main BDUJPO XJUI BO PCMJHBUPSZ *0
UZQF #VU XFƊMM HFU UP UIBU JO B NPNFOU
'PS OPX MFUƊT UVSO PVS BUUFOUJPO UP XIBU TIBSJOH JT EJTBCMFE
BOE XIZ 6TVBMMZ JO )BTLFMM XFƊSF QSFUUZ DPOƶEFOU UIBU JG B
GVODUJPO JT HPJOH UP CF FWBMVBUFE BU BMM JU XJMM SFTVMU JO B WBMVF
PG B DFSUBJO UZQF CFBSJOH JO NJOE UIBU UIJT DPVME CF B /PUIJOH
WBMVF PS BO FNQUZ MJTU 8IFO XF EFDMBSF UIF UZQF XF TBZ ƌJG
UIJT JT FWBMVBUFE BU BMM XF XJMM IBWF B WBMVF PG UIJT UZQF BT B
SFTVMUƍ
#VU XJUI UIF *0 UZQF ZPVƊSF OPU HVBSBOUFFE BOZUIJOH 7BM
VFT PG UZQF IO a BSF OPU BO Ԑ UIFZƊSF B EFTDSJQUJPO PG IPX ZPV
NJHIU HFU BO Ԑ " GVODUJPO PG UZQF *0 4USJOH JT OPU B DPNQVUB
UJPO UIBU JG FWBMVBUFE XJMM SFTVMU JO B 4USJOH JUƊT B EFTDSJQUJPO PG
IPX ZPV NJHIU HFU UIBU 4USJOH GSPN UIF ƌSFBM XPSME ƍ QPTTJCMZ
QFSGPSNJOH FƵFDUT BMPOH UIF XBZ %FTDSJCJOH *0 BDUJPOT EPFT
OPU QFSGPSN UIFN KVTU BT IBWJOH B SFDJQF GPS B DBLF EPFT OPU
HJWF ZPV B DBLF
*O UIJT FOWJSPONFOU XIFSF ZPV EP OPU IBWF B WBMVF CVU
POMZ B NFBOT PG HFUUJOH B WBMVF JU XPVMEOƊU NBLF TFOTF UP TBZ
UIBU WBMVF DPVME CF TIBSFE

4FF #SFOU :PSHFZƊT FYQMBOBUJPO PG *0 GPS UIF DJT DMBTT BU 61FOO http://www.cis.
upenn.edu/~cis194/spring13/lectures/08-IO.html
$)"15&3  *0 

5IF UJNF IBT DPNF


4P POF PG UIF LFZ GFBUVSFT PG *0 JT UIBU JU UVSOT PƵ TIBSJOH
-FUƊT VTF BO FYBNQMF UP UIJOL PG XIZ XF XBOU UIJT 8F IBWF
UIJT MJCSBSZ GVODUJPO UIBU HFUT UIF DVSSFOU 65$ UJNF GSPN UIF
TZTUFN DMPDL

-- from Data.Time.Clock
getCurrentTime :: IO UTCTime

8JUIPVU *0 QSFWFOUJOH TIBSJOH IPX XPVME UIJT XPSL 8IFO


ZPV GFUDIFE UIF UJNF PODF JU XPVME TIBSF UIBU SFTVMU BOE UIF
UJNF XPVME CF XIBUFWFS UJNF JU XBT UIF ƶSTU UJNF ZPV GPSDFE JU
6OGPSUVOBUFMZ UIJT JT OPU B NFBOT PG TUPQQJOH UJNF XF XPVME
DPOUJOVF UP BHF CVU ZPVS QSPHSBN XPVMEOƊU XPSL BU BMM UIF
XBZ ZPVƊE JOUFOEFE
#VU JG UIBUƊT TP BOE JUƊT DMFBSMZ B WBMVF XJUI B OBNF UIBU DPVME
CF TIBSFE XIZ JTOƊU JU

getCurrentTime :: IO UTCTime
-- ^-- that right there

3FNFNCFS XIBU XF IBWF IFSF JT B EFTDSJQUJPO PG IPX XF


DBO HFU UIF DVSSFOU UJNF XIFO XF OFFE JU 8F EP OPU IBWF UIF
DVSSFOU UJNF ZFU TP JU JTOƊU B WBMVF UIBU DBO CF TIBSFE BOE XF
EPOƊU XBOU JU UP CF TIBSFE BOZXBZ CFDBVTF XF XBOU JU UP HFU B
OFX UJNF FBDI UJNF XF SVO JU
$)"15&3  *0 

"OE UIF XBZ XF SVO JU JT CZ EFƶOJOH main JO UIBU NPEVMF


GPS UIF SVOUJNF TZTUFN UP ƶOE BOE FYFDVUF &WFSZUIJOH JOTJEF
main JT XJUIJO *0 TP UIBU FWFSZUIJOH JT OFTUFE BOE TFRVFODFE
BOE IBQQFOT JO UIF PSEFS ZPVƊSF FYQFDUJOH

"OPUIFS FYBNQMF
-FUƊT MPPL BU BOPUIFS FYBNQMF PG *0 UVSOJOH PƵ TIBSJOH :PV
SFNFNCFS UIF whnf BOE nf GVODUJPOT GSPN DSJUFSJPO UIBU XF
VTFE JO UIF MBTU DIBQUFS :PV NBZ SFDBMM UIBU XF XBOU UP UVSO
PƵ TIBSJOH GPS UIPTF TP UIBU UIFZ HFU FWBMVBUFE PWFS BOE PWFS
BHBJO JG UIF SFTVMU XBT TIBSFE PVS CFODINBSLJOH XPVME POMZ
UFMM VT IPX MPOH JU UBLFT UP FWBMVBUF JU PODF JOTUFBE PG HJWJOH VT
BO BWFSBHF PG FWBMVBUJOH JU NBOZ UJNFT 5IF XBZ XF EJTBCMFE
TIBSJOH GPS UIPTF GVODUJPO JT CZ BQQMZJOH UIFN UP BSHVNFOUT
#VU UIF *0 WBSJBOUT PG UIPTF GVODUJPOT EP OPU SFRVJSF UIJT
GVODUJPO BQQMJDBUJPO JO PSEFS UP EJTBCMF TIBSJOH CFDBVTF UIF
*0 QBSBNFUFS JUTFMG EJTBCMFT TIBSJOH $POUSBTU UIF GPMMPXJOH
UZQFT

whnf :: (a -> b) -> a -> Benchmarkable


nf :: NFData b => (a -> b) -> a -> Benchmarkable

whnfIO :: IO a -> Benchmarkable


nfIO :: NFData a => IO a -> Benchmarkable
$)"15&3  *0 

5IF *0 WBSJBOUT EPOƊU OFFE B GVODUJPO BSHVNFOU UP BQQMZ


CFDBVTF TIBSJOH JT BMSFBEZ QSFWFOUFE CZ CFJOH BO *0 BDUJPO ƈ
JU DBO CF FYFDVUFE PWFS BOE PWFS XJUIPVU SFTPSUJOH UP BEEJOH
BO BSHVNFOU
"T XF TBJE FBSMJFS *0 EPFTOƊU UVSO PƵ BMM TIBSJOH FWFSZXIFSF
JU DPVMEOƊU PS FMTF TIBSJOH XPVME CF NFBOJOHMFTT CFDBVTF main
JT BMXBZT JO *0 #VU JUƊT JNQPSUBOU UP VOEFSTUBOE XIFO TIBSJOH
XJMM CF EJTBCMFE BOE XIZ CFDBVTF JG ZPVƊWF HPU UIJT OPUJPO PG
TIBSJOH SVOOJOH BSPVOE JO UIF CBDL PG ZPVS IFBE ZPVƊMM IBWF
UIF XSPOH JOUVJUJPOT GPS IPX )BTLFMM DPEF XPSLT 8IJDI UIFO
MFBET UPƒ

5IF DPEF *U EPFTOƊU XPSL


8FƊSF HPJOH UP VTF BO FYBNQMF IFSF UIBU UBLFT BEWBOUBHF PG
UIF .7BS UZQF 5IJT JT CBTFE PO B SFBM DPEF FWFOU UIBU XBT IPX
$ISJT ƶOBMMZ MFBSOFE XIBU *0 SFBMMZ NFBOT BOE UIF FYBNQMF
IF ƶSTU VTFE UP FYQMBJO JU UP +VMJF
5IF .7BS UZQF JT B NFBOT PG TZODISPOJ[JOH TIBSFE EBUB JO
)BTLFMM 5P HJWF B WFSZ DVSTPSZ PWFSWJFX UIF .7BS DBO IPME
POF WBMVF BU B UJNF :PV QVU B WBMVF JOUP JU JU IPMET POUP JU
VOUJM ZPV UBLF UIBU WBMVF PVU 5IFO BOE POMZ UIFO DBO ZPV QVU
BOPUIFS DBU JO UIF CPY 8F DBOOPU SFBMMZ IPQF UP CFTU 4JNPO

8IBU ZPV OFFE JT B DBU HJG https://twitter.com/argumatronic/status/
631158432859488258
$)"15&3  *0 

.BSMPXƊT XPSL PO UIJT GSPOU TP JG ZPV XBOU NPSF JOGPSNBUJPO


BCPVU JU XF TUSPOHMZ SFDPNNFOE ZPV QFSVTF .BSMPXƊT CPPL
0, TP XFƊMM TFU VQ TPNF UPZ DPEF IFSF XJUI UIF JEFB UIBU
XF XBOU UP QVU B WBMVF JOUP BO .7BS BOE UIFO UBLF JU CBDL PVU

module WhatHappens where

import Control.Concurrent

myData :: IO (MVar Int)


myData = newEmptyMVar

main :: IO ()
main = do
mv <- myData
putMVar mv 0
mv' <- myData
zero <- takeMVar mv'
print zero

5IJT XJMM TQFX BO FSSPS BCPVU CFJOH TUVDL PS JO B EFBEMPDL


5IF QSPCMFN IFSF JT UIBU UIF UZQF IO MVar a PG newEmptyMVar JT
B SFDJQF GPS QSPEVDJOH BT NBOZ FNQUZ .7BST BT ZPV OFFE PS
XBOU JU JT OPU B SFGFSFODF UP B TJOHMF TIBSFE .7BS *O PUIFS

1BSBMMFM  $PODVSSFOU 1SPHSBNNJOH JO )BTLFMM http://chimera.labs.oreilly.com/
books/1230000000929
$)"15&3  *0 

XPSET UIF UXP SFGFSFODFT UP myData IFSF BSF OPU SFGFSSJOH UP


UIF TBNF .7BS
5BLJOH GSPN BO FNQUZ .7BS CMPDLT VOUJM TPNFUIJOH JT QVU
JOUP UIF .7BS $POTJEFS UIF GPMMPXJOH PSEFSJOH

take
put
take
put

5IBU XJMM UFSNJOBUF TVDDFTTGVMMZ "O BUUFNQU UP UBLF B WBMVF


GSPN UIF .7BS CMPDLFE UIFO B WBMVF XBT QVU JO JU UIFO BOPUIFS
CMPDLFE UBLF PDDVSSFE UIFO UIFSF XBT BOPUIFS QVU UP TBUJTGZ
UIF TFDPOE UBLF 5IJT JT ƶOF
5IF GPMMPXJOH JT BO FYBNQMF PG TPNFUIJOH UIBU XJMM EFBE
MPDL

put
take
take

8IBUFWFS QBSU PG ZPVS QSPHSBN QFSGPSNFE UIF TFDPOE UBLF


XJMM OPX CF CMPDLFE VOUJM B TFDPOE QVU PDDVST *G ZPVS QSPHSBN
JT EFTJHOFE TVDI UIBU OP QVU FWFS PDDVST BHBJO JUƊT EFBEMPDLFE
" EFBEMPDL FSSPS MPPLT MJLF UIF GPMMPXJOH

Prelude> main
$)"15&3  *0 

*** Exception:
thread blocked indefinitely in an MVar operation

8IFO ZPV TFF B UZQF MJLF

IO String

:PV EPOƊU IBWF B 4USJOH ZPV IBWF B NFBOT PG QPTTJCMZ

PCUBJOJOH B 4USJOH JG ZPV NBZCF


QFSGPSN TPNF FƵFDUT BMPOH
UIF XBZ 4JNJMBSMZ XIBU IBQQFOFE FBSMJFS JT UIBU XF IBE UXP
.7BST XJUI UXP EJƵFSFOU MJGFUJNFT BOE UIBU MPPLFE TPNFUIJOH
MJLF UIJT

mv mv'
put take (the final one)

5IF QPJOU IFSF JT UIBU UIJT UZQF

IO (MVar a)

UFMMT ZPV UIBU ZPV IBWF B SFDJQF GPS QSPEVDJOH BT NBOZ


FNQUZ .7BST BT ZPV XBOU OPU B SFGFSFODF UP B TJOHMF TIBSFE
.7BS
:PV DBO TIBSF UIF .7BS CVU JU IBT UP CF EPOF FYQMJDJUMZ
SBUIFS UIBO JNQMJDJUMZ 'BJMJOH UP FYQMJDJUMZ TIBSF UIF .7BS SFG
FSFODF BǒFS CJOEJOH JU PODF XJMM TJNQMZ TQFX PVU OFX FNQUZ
.7BST "HBJO XF SFDPNNFOE 4JNPO .BSMPXƊT CPPL XIFO
ZPVƊSF SFBEZ UP FYQMPSF .7BST JO NPSF EFUBJM
$)"15&3  *0 

 *0 EPFTOƊU EJTBCMF TIBSJOH GPS


FWFSZUIJOH
"T XF NFOUJPOFE FBSMJFS *0 EPFTOƊU EJTBCMF TIBSJOH GPS FW
FSZUIJOH BOE JU XPVMEOƊU SFBMMZ NBLF TFOTF JG JU EJE *U POMZ
EJTBCMFT TIBSJOH GPS UIF UFSNJOBM WBMVF JU SFEVDFT UP 7BMVFT
UIBU BSF OPU EFQFOEFOU PO *0 GPS UIFJS FWBMVBUJPO DBO TUJMM CF
TIBSFE FWFO XJUIJO B MBSHFS *0 BDUJPO TVDI BT main
*O UIF GPMMPXJOH FYBNQMF XFƊMM VTF %FCVH5SBDF BHBJO UP
TIPX VT XIFO UIJOHT BSF CFJOH TIBSFE 'PS blah UIF trace JT
PVUTJEF UIF *0 BDUJPO TP XFƊMM VTF outer trace

import Debug.Trace

blah :: IO String
blah = return "blah"

blah' = trace "outer trace" blah

"OE GPS woot XFƊMM VTF inner trace JOTJEF UIF *0 BDUJPO

woot :: IO String
woot = return (trace "inner trace" "woot")

5IFO XF UISPX CPUI PG UIFN JOUP B MBSHFS *0 BDUJPO main


$)"15&3  *0 

main :: IO ()
main = do
b <- blah'
putStrLn b
putStrLn b
w <- woot
putStrLn w
putStrLn w

Prelude> main
outer trace
blah
blah
inner trace
woot
woot

8F POMZ TBX JOOFS BOE PVUFS FNJUUFE PODF CFDBVTF *0 JT OPU


JOUFOEFE UP EJTBCMF TIBSJOH GPS WBMVFT OPU JO *0 UIBU IBQQFO
UP CF VTFE JO UIF DPVSTF PG SVOOJOH PG BO *0 BDUJPO

 1VSJUZ JT MPTJOH NFBOJOH


*UƊT DPNNPO BU UIJT UJNF UP VTF UIF XPSET ƌQVSFMZ GVODUJPOBMƍ
PS UP UBML BCPVU QVSJUZ XIFO POF NFBOT XJUIPVU FƵFDUT 5IJT JT JO
$)"15&3  *0 

BDDVSBUF BOE OPU WFSZ VTFGVM BT B EFƶOJUJPO CVU XFƊSF HPJOH UP


QSPWJEF TPNF DPOUFYU IFSF BOE BO BMUFSOBUJWF VOEFSTUBOEJOH

4FNBOUJDBMMZ QFEBOUJDBMMZ BDDVSBUF


1VSJUZ BOE ƌQVSF GVODUJPOBMƍ IBWF VOEFSHPOF B GFX DIBOHFT JO
DPOOPUBUJPO BOE EFOPUBUJPO TJODF UIF T 8IBU XBT PSJHJ
OBMMZ NFBOU XIFO EFTDSJCJOH B QVSF GVODUJPOBM QSPHSBNNJOH
MBOHVBHF JT UIBU UIF TFNBOUJDT PG UIF MBOHVBHF XPVME POMZ CF
MBNCEB DBMDVMVT 'PS RVJUF B MPOH UJNF JNQVSF GVODUJPOBM MBO
HVBHFT XFSF NPSF UZQJDBM 5IFZ BENJUUFE UIF BVHNFOUBUJPO PG
MBNCEB DBMDVMVT VTVBMMZ TP UIBU UIF NFBOT UP EFTDSJCF JNQFS
BUJWF FƵFDUGVM QSPHSBNT XBT FNCFEEFE XJUIJO UIF TFNBOUJDT
5IF TUSFOHUI PG )BTLFMM JT UIBU CZ TUJDLJOH UP MBNCEB DBMDVMVT
XF OPU POMZ IBWF B NVDI TJNQMFS DPSF MBOHVBHF GPS EFTDSJCJOH
PVS MBOHVBHF CVU XF SFUBJO SFGFSFOUJBM USBOTQBSFODZ JO UIF
MBOHVBHF 8F VTF OFTUFE MBNCEBT IJEEFO CFIJOE B .POBE BC
TUSBDUJPO
UP PSEFS BOE FODBQTVMBUF FƵFDUT XIJMF NBJOUBJOJOH
SFGFSFOUJBM USBOTQBSFODZ

3FGFSFOUJBM USBOTQBSFODZ
3FGFSFOUJBM USBOTQBSFODZ JT TPNFUIJOH ZPV BSF QSPCBCMZ GBNJMJBS
XJUI FWFO JG ZPVƊWF OFWFS DBMMFE JU UIBU CFGPSF 1VU DBTVBMMZ JU
NFBOT UIBU BOZ GVODUJPO XIFO HJWFO UIF TBNF JOQVUT SFUVSOT
UIF TBNF SFTVMU .PSF QSFDJTFMZ BO FYQSFTTJPO JT SFGFSFOUJBMMZ
$)"15&3  *0 

USBOTQBSFOU XIFO JU DBO CF SFQMBDFE XJUI JUT WBMVF XJUIPVU


DIBOHJOH UIF CFIBWJPS PG B QSPHSBN
0OF TPVSDF PG UIF DPOGVTJPO CFUXFFO QVSJUZ BT SFGFSFOUJBM
USBOTQBSFODZ BOE QVSJUZ BT QVSF MBNCEB DBMDVMVT DPVME CF UIBU
JO B QVSF MBNCEB DBMDVMVT SFGFSFOUJBM USBOTQBSFODZ JT BTTVSFE
5IVT B QVSF MBNCEB DBMDVMVT JT OFDFTTBSJMZ QVSF JO UIF PUIFS
TFOTF BT XFMM
5IF NJTUBLF QFPQMF NBLF XJUI *0 JT UIBU UIFZ DPOƷBUF UIF
FƵFDUT XJUI UIF TFNBOUJDT PG UIF QSPHSBN " GVODUJPO UIBU
SFUVSOT IO a JT TUJMM SFGFSFOUJBMMZ USBOTQBSFOU CFDBVTF HJWFO UIF
TBNF BSHVNFOUT JUƊMM HFOFSBUF UIF TBNF *0 BDUJPO FWFSZ UJNF
5P NBLF UIJT QPJOU

module IORefTrans where

import Control.Monad (replicateM)


import System.Random (randomRIO)

gimmeShelter :: Bool -> IO [Int]


gimmeShelter True = replicateM 10 (randomRIO (0, 10))
gimmeShelter False = pure [0]

5IF USJDL IFSF JT UP SFBMJ[F UIBU XIJMF FYFDVUJOH IO [Int] DBO


BOE EPFT QSPEVDF EJƵFSFOU MJUFSBM WBMVFT XIFO UIF BSHVNFOU
JT 5SVF JUƊT TUJMM QSPEVDJOH UIF TBNF SFTVMU JF B MJTU PG SBO
EPN OVNCFST
GPS UIF TBNF JOQVU 3FGFSFOUJBM USBOTQBSFODZ JT
$)"15&3  *0 

QSFTFSWFE CFDBVTF XFƊSF TUJMM SFUVSOJOH UIF TBNF *0 BDUJPO PS


ƌSFDJQF ƍ GPS UIF TBNF BSHVNFOU UIF TBNF NFBOT PG PCUBJOJOH
B MJTU PG *OU &WFSZ 5SVF JOQVU UP UIJT GVODUJPO XJMM SFUVSO B MJTU
PG SBOEPN *OUT

Prelude> gimmeShelter True


[1,8,7,9,10,4,2,9,3,6]
Prelude> gimmeShelter True
[10,0,7,1,10,2,4,0,9,3]
Prelude> gimmeShelter False
[0]

5IF TFOTF XFƊSF USZJOH UP DPOWFZ IFSF JT UIBU BT GBS BT )BTLFMM


JT DPODFSOFE JUƊT B MBOHVBHF GPS FWBMVBUJOH FYQSFTTJPOT BOE
DPOTUSVDUJOH *0 BDUJPOT UIBU HFU FYFDVUFE CZ main BU TPNF QPJOU
MBUFS

 *0ƊT 'VODUPS "QQMJDBUJWF BOE


.POBE
"OPUIFS NJTUBLF QFPQMF NBLF JT JO JNQMZJOH UIBU *0 JT B .POBE
SBUIFS UIBO BDDPVOUJOH GPS UIF GBDU UIBU MJLF BMM .POBET *0 JT
B EBUBUZQF UIBU IBT B .POBE JOTUBODF ƈ BT XFMM BT 'VODUPS BOE
"QQMJDBUJWF JOTUBODFT
fmap DPOTUSVDU BO BDUJPO XIJDI QFSGPSNT UIF TBNF FƵFDUT
CVU USBOTGPSNT UIF Ԑ JOUP B ԑ
$)"15&3  *0 

fmap :: (a -> b) -> IO a -> IO b

(<*>) DPOTUSVDU BO BDUJPO UIBU QFSGPSNT UIF FƵFDUT PG CPUI


UIF GVODUJPO BOE WBMVF BSHVNFOUT BQQMZJOH UIF GVODUJPO UP
UIF WBMVF

(<*>) :: IO (a -> b) -> IO a -> IO b

join NFSHF UIF FƵFDUT PG B OFTUFE *0 BDUJPO

join :: IO (IO a) -> IO a

5IF *0 'VODUPS
8IBU EPFT GNBQ NFBO XJUI SFTQFDU UP *0 "T BMXBZT XF XBOU
BO FYBNQMF

fmap (+1) (randomIO :: IO Int)

*G XFƊSF HPJOH UP HFU UIBU *OU WBMVF XF XJMM IBWF UP QFSGPSN


TPNF FƵFDUT 8IBU fmap EPFT IFSF JT MJǒ PVS JODSFNFOUJOH
GVODUJPO PWFS UIF FƵFDUT UIBU XF NJHIU QFSGPSN UP PCUBJO
UIF *OU WBMVF *U EPFTOƊU BƵFDU UIF FƵFDUT CFDBVTF UIF FƵFDUT
IFSF BSF QBSU PG UIBU *0 TUSVDUVSF 6TJOH fmap IFSF SFUVSOT B
SFDJQF GPS PCUBJOJOH BO *OU UIBU BMTP JODSFNFOUT UIF SFTVMU PG
UIF PSJHJOBM BDUJPO UIBU XBT MJǒFE PWFS
5IF LFZ IFSF JT UIBU XF EJEOƊU QFSGPSN BOZ FƵFDUT 8F QSP
EVDFE B OFX *0 BDUJPO JO UFSNT PG UIF PME POF CZ USBOTGPSNJOH
UIF ƶOBM SFTVMU PG UIF *0 BDUJPO
$)"15&3  *0 

"QQMJDBUJWF BOE *0
*0 BMTP IBT BO "QQMJDBUJWF JOTUBODF BT XF NFOUJPOFE JO UIF
"QQMJDBUJWF DIBQUFS :PV NJHIU SFNFNCFS BO FYBNQMF MJLF
UIJT

Prelude> (++) <$> getLine <*> getLine


hello
julie
"hellojulie"

5IFSF XF GNBQQFE UIF DPODBUFOBUJPO PQFSBUPS PWFS UXP


QPUFOUJBM
*0 4USJOHT UP QSPEVDF UIF ƶOBM SFTVMU -FUƊT MPPL BU
BOPUIFS NPSF JOUFSFTUJOH FYBNQMF

(+) <$> (randomIO :: IO Int) <*> (randomIO :: IO Int)

"ǒFS UIF JOJUJBM fmap XF IBWF B NFBOT PG PCUBJOJOH B GVOD


UJPO XIJDI JT NPOPJEBMMZ MJǒFE PWFS B NFBOT PG PCUBJOJOH BO
*OU 8IBU UIJT NFBOT JT UIBU ZPVƊMM HFU B TJOHMF OFX NFBOT
PG PCUBJOJOH UIF SFTVMU PG IBWJOH BQQMJFE UIF GVODUJPO XIJDI
QFSGPSNT UIF FƵFDUT PG CPUI

.POBE BOE *0
'PS *0 pure PS return DBO CF SFBE BT BO FƵFDUGSFF FNCFEEJOH
PG B WBMVF JO B SFDJQFDSFBUJOH FOWJSPONFOU MFU VT DPOTJEFS
UIF GPMMPXJOH FYBNQMFT
$)"15&3  *0 

'JSTU ()$J EPFT CBTJDBMMZ UXP UIJOHT JU DBO QSJOU WBMVFT


OPU JO *0 TVDI BT UIFTF

Prelude> "I'll pile on the candy"


"I'll pile on the candy"
Prelude> 1
1

*U DBO BMTP SVO *0 BDUJPOT BOE QSJOU UIFJS SFTVMUT JG BOZ


8IFO ZPV IBWF WBMVFT PG UZQF IO (IO a) XIBU ZPV IBWF JT B
SFDJQF GPS NBLJOH B SFDJQF UIBU QSPEVDFT BO Ԑ $POTJEFS XIZ
UIF GPMMPXJOH FYBNQMF VTJOH print EPFT OPU QSJOU BOZUIJOH

Prelude> let embedInIO = return :: a -> IO a


Prelude> embedInIO 1
1
Prelude> embedInIO (print "I'll put in some ingredients")

*O PSEFS UP NFSHF UIPTF FƵFDUT BOE HFU B TJOHMF IO a XIJDI


XJMM QSJOU B SFTVMU JO ()$J XF OFFE join

Prelude> join $ embedInIO (print "It's a piece of cake")


"It's a piece of cake"
Prelude> embedInIO (embedInIO 1)
Prelude> join $ embedInIO (embedInIO 1)
1
$)"15&3  *0 

8IBU TFUT UIF *0 NPOBE BQBSU GSPN UIF "QQMJDBUJWF JT UIBU


UIF FƵFDUT QFSGPSNFE CZ UIF PVUFS *0 BDUJPO DBO JOƷVFODF
XIBU SFDJQF ZPV HFU JO UIF JOOFS QBSU 5IF OFTUJOH BMTP MFUT VT
FYQSFTT PSEFS EFQFOEFODF B VTFGVM USJDL GPS MBNCEB DBMDVMJ
OPUFE CZ 1FUFS + -BOEJO 
"O FYBNQMF GPS FƵFDU

module NestedIO where

import Data.Time.Calendar
import Data.Time.Clock
import System.Random

huehue :: IO (Either (IO Int) (IO ()))


huehue = do
t <- getCurrentTime
let (_, _, dayOfMonth) =
toGregorian (utctDay t)
case even dayOfMonth of
True ->
return $ Left randomIO
False ->
return $ Right (putStrLn "no soup for you")

5IF *0 BDUJPO XF SFUVSO IFSF JT DPOUJOHFOU PO IBWJOH QFS



" DPSSFTQPOEFODF CFUXFFO "-(0-  BOE $IVSDIƊT -BNCEBOPUBUJPOT 1+ -BOEJO
$)"15&3  *0 

GPSNFE FƵFDUT BOE PCTFSWFE XIFUIFS UIF EBZ PG UIF NPOUI


XBT BO FWFO OVNCFS PS BO PEE POF /PUF UIJT JT JOFYQSFTTJCMF
XJUI "QQMJDBUJWF *G ZPVƊE MJLF B XBZ UP SVO JU BOE TFF XIBU
IBQQFOT USZ UIF GPMMPXJOH

Prelude> blah <- huehue


Prelude> either (>>= print) id blah
-7077132465932290066

*U XBT UIF UI PG +BOVBSZ XIFO XF XSPUF UIJT :PVS NJMFBHF


NBZ WBSZ

.POBEJD BTTPDJBUJWJUZ
)BTLFMMFST XJMM PǒFO HFU DPOGVTFE XIFO UIFZ BSF UPME .POBEƊT
CJOE JT BTTPDJBUJWF CFDBVTF UIFZƊMM UIJOL PG *0 BT B DPVOUFS
FYBNQMF 5IF NJTUBLF CFJOH NBEF IFSF JT NJTUBLJOH UIF DPO
TUSVDUJPO PG *0 BDUJPOT GPS UIF FYFDVUJPO PG *0 BDUJPOT "T GBS
BT )BTLFMM JT DPODFSOFE XF POMZ DPOTUSVDU *0 BDUJPOT UP CF
FYFDVUFE XIFO XF DBMM main 4FNBOUJDBMMZ *0 BDUJPOT BSFOƊU
TPNFUIJOH XF EP CVU TPNFUIJOH XF UBML BCPVU #JOEJOH PWFS
BO *0 BDUJPO EPFTOƊU FYFDVUF JU JU QSPEVDFT B OFX *0 BDUJPO JO
UFSNT PG UIF PME POF
:PV DBO SFDPODJMF ZPVSTFMG XJUI UIJT GSBNJOH CZ SFNFN
CFSJOH IPX *0 BDUJPOT BSF MJLF SFDJQFT BO BOBMPHZ DSFBUFE CZ
#SFOU :PSHFZ UIBU XFƊSF GPOE PG

8IZ .POBE DIBQUFSƊT MPOH QBTTFE XF OFFE TPNFUIJOH UP CF TQPPLZ
$)"15&3  *0 

 8FMM UIFO IPX EP XF .7BS


&BSMJFS JO UIF DIBQUFS XF TIPXFE ZPV BO FYBNQMF PG XIFO
*0 QSFWFOUT TIBSJOH VTJOH UIF .7BS UZQF 0VS QSFWJPVT DPEF
XPVME CMPDL CFDBVTF UIF GPMMPXJOH

myData :: IO (MVar Int)


myData = newEmptyMVar

JT BO *0 BDUJPO UIBU QSPEVDFT BO FNQUZ .7BS JU JTOƊU B TUBCMF


SFGFSFODF UP B TJOHMF HJWFO .7BS 8F IBWF B DPVQMF XBZT PG
ƶYJOH UIJT 0OF JT CZ QBTTJOH UIF TJOHMF TUBCMF SFGFSFODF BT BO
BSHVNFOU 5IF GPMMPXJOH XJMM UFSNJOBUF TVDDFTTGVMMZ

module WhatHappens where

import Control.Concurrent

main :: IO ()
main = do
mv <- newEmptyMVar
putMVar mv (0 :: Int)
zero <- takeMVar mv
print zero

5IFSF JT B TPNFXIBU NPSF FWJM BOE VOOFDFTTBSZ XBZ PG


EPJOH JU 8FƊMM VTF UIJT PQQPSUVOJUZ UP FYBNJOF BO VOTBGF NFBOT
$)"15&3  *0 

PG FOBCMJOH TIBSJOH GPS BO *0 BDUJPO unsafePerformIO $POTJEFS


UIBU UIF GPMMPXJOH XJMM BMTP UFSNJOBUF

module WhatHappens where

import Control.Concurrent
import System.IO.Unsafe

myData :: MVar Int


myData = unsafePerformIO newEmptyMVar

main :: IO ()
main = do
putMVar myData 0
zero <- takeMVar myData
print zero

5IF UZQF PG unsafePerformIO JT IO a -> a XIJDI JT TFFNJOHMZ


JNQPTTJCMF BOE OPU B HPPE JEFB JO HFOFSBM *O SFBM DPEF ZPV
TIPVME QBTT SFGFSFODFT UP .7BST BT BO BSHVNFOU PS WJB 3FBEFS3FBE
FS5 CVU UIF DPNCJOBUJPO PG .7BS BOE unsafePerformIO HJWFT VT
BO PQQPSUVOJUZ UP TFF JO WFSZ TUBSL UFSNT XIBU JU NFBOT UP VTF
unsafePerformIO JO PVS DPEF 5IF OFX FNQUZ .7BS DBO OPX CF
TIBSFE JNQMJDJUMZ BT PǒFO BT ZPV XBOU JOTUFBE PG DSFBUJOH B
OFX POF FBDI UJNF
$)"15&3  *0 

%P OPU VTF VOTBGF1FSGPSN*0 XIFO VOOFDFTTBSZ PS XIFSF


JU DPVME CSFBL SFGFSFOUJBM USBOTQBSFODZ JO ZPVS DPEF *G ZPV
BSFOƊU TVSF ƈ EPOƊU VTF JU 5IFSF BSF PUIFS VOTBGF *0 GVODUJPOT
UPP CVU UIFSF JT SBSFMZ B OFFE GPS BOZ PG UIFN BOE JO HFOFSBM
ZPV TIPVME QSFGFS FYQMJDJU SBUIFS UIBO JNQMJDJU

 $IBQUFS &YFSDJTFT


'JMF *0 XJUI 7JHFO¨SF
3FVTJOH UIF 7JHFO¨SF DJQIFS ZPV XSPUF CBDL JO BMHFCSBJD EBUBUZQFT
BOE XSPUF UFTUT GPS JO UFTUJOH NBLF BO FYFDVUBCMF UIBU UBLFT
B LFZ BOE B NPEF BSHVNFOU *G UIF NPEF JT -d UIF FYFDVUBCMF
EFDSZQUT UIF JOQVU GSPN TUEJO BOE XSJUFT UIF EFDSZQUFE UFYU
UP TUBOEBSE PVU *G UIF NPEF JT -e UIF FYFDVUBCMF CMPDLT PO
JOQVU GSPN TUBOEBSE JOQVU BOE XSJUFT UIF FODSZQUFE PVUQVU UP
TUEPVU
$POTJEFS UIJT BO PQQPSUVOJUZ UP MFBSO NPSF BCPVU IPX ƶMF
IBOEMFT BOE UIF GPMMPXJOH NFNCFST PG UIF CBTF MJCSBSZ XPSL

System.Environment.getArgs :: IO [String]
System.IO.hPutStr :: Handle -> String -> IO ()
System.IO.hGetChar :: Handle -> IO Char
System.IO.stdout :: Handle
System.IO.stdin :: Handle
$)"15&3  *0 

8IBUFWFS 04 ZPVƊSF PO ZPVƊMM OFFE UP MFBSO IPX UP GFFE


ƶMFT BT JOQVU UP ZPVS VUJMJUZ BOE IPX UP SFEJSFDU TUBOEBSE PVU
UP B ƶMF 1BSU PG UIF FYFSDJTF JT ƶHVSJOH UIJT PVU GPS ZPVSTFMG

"EE UJNFPVUT UP ZPVS VUJMJUZ

6TF I8BJU'PS*OQVU UP NBLF ZPVS VUJMJUZ UJNFPVU JG OP JOQVU


JT QSPWJEFE XJUIJO B TQBO PG UJNF PG ZPVS DIPPTJOH :PV DBO
NBLF JU BO PQUJPOBM DPNNBOEMJOF BSHVNFOU &YJU XJUI B
OPO[FSP FSSPS DPEF BOE BO FSSPS NFTTBHF QSJOUFE UP TUBOEBSE
FSSPS TUEFSS
JOTUFBE PG TUEPVU

System.IO.hWaitForInput :: Handle -> Int -> IO Bool


System.IO.stderr :: Handle

$POƶH EJSFDUPSJFT
3FVTJOH UIF */* QBSTFS GSPN UIF 1BSTJOH DIBQUFS QBSTF B EJ
SFDUPSZ PG JOJ DPOƶH ƶMFT JOUP B .BQ XIPTF LFZ JT UIF ƶMFOBNF
BOE XIPTF WBMVF JT UIF SFTVMU PG QBSTJOH UIF */* ƶMF 0OMZ QBSTF
ƶMFT JO UIF EJSFDUPSZ UIBU IBWF UIF ƶMF FYUFOTJPO .ini

 'PMMPXVQ SFTPVSDFT


 3FGFSFOUJBM 5SBOTQBSFODZ )BTLFMM 8JLJ
https://wiki.haskell.org/Referential_transparency
$)"15&3  *0 

 *0 *OTJEF )BTLFMM 8JLJ


https://wiki.haskell.org/IO_inside

 6OSBWFMJOH UIF NZTUFSZ PG UIF *0 .POBE &EXBSE ; :BOH

 1SJNJUJWF )BTLFMM .JDIBFM 4OPZNBO


https://github.com/commercialhaskell/haskelldocumentation/
blob/master/content/primitive-haskell.md

 &WBMVBUJPO PSEFS BOE TUBUF UPLFOT .JDIBFM 4OPZNBO


https://wiki.haskell.org/Evaluation_order_and_state_tokens

 )BTLFMM ()$ *MMVTUSBUFE 5BLFOPCV 5BOJ

 5BDLMJOH UIF "XLXBSE 4RVBE 4JNPO 1&:50/ +0/&4


http://research.microsoft.com/en-us/um/people/simonpj/papers/
marktoberdorf/mark.pdf

 /PUF <*0 IBDL JO UIF EFNBOE BOBMZTFS> ()$ TPVSDF DPEF

 .POBEJD *0 JO )BTLFMM  "OESFX % (PSEPO BOE ,FWJO


)BNNPOE

 /PUJPOT PG DPNQVUBUJPO BOE NPOBET &VHFOJP .PHHJ


http://www.disi.unige.it/person/MoggiE/ftp/ic91.pdf

 5IF /FYU  1SPHSBNNJOH -BOHVBHFT 1 + -BOEJO

 )BTLFMM 3FQPSU 


$IBQUFS 

8IFO UIJOHT HP XSPOH

*U JT FBTJFS UP XSJUF BO
JODPSSFDU QSPHSBN UIBO
VOEFSTUBOE B DPSSFDU POF

"MBO 1FSMJT


$)"15&3  8)&/ 5)*/(4 (0 830/( 

 &YDFQUJPOT
-FUƊT GBDF JU JO UIF FYFDVUJPO PG B QSPHSBN B MPU PG UIJOHT DBO
IBQQFO OPU BMM PG UIFN FYQFDUFE PS EFTJSFE *O UIPTF VOIBQQZ
UJNFT XIFO UIJOHT IBWF OPU HPOF BT XF XBOUFE UIFN UP XF
XJMM UISPX PS SBJTF BO FYDFQUJPO 5IF UFSN FYDFQUJPO SFGFST
UP UIF DPOEJUJPO UIBU IBT JOUFSSVQUFE UIF FYQFDUFE FYFDVUJPO
PG UIF QSPHSBN &ODPVOUFSJOH BO FYDFQUJPO DBVTFT BO FSSPS
PS FYDFQUJPO NFTTBHF UP BQQFBS JOGPSNJOH ZPV UIBU EVF UP
TPNF DPOEJUJPO ZPV XFSFOƊU QSFQBSFE GPS UIF FYFDVUJPO PG UIF
QSPHSBN IBT IBMUFE JO BO VOGPSUVOBUF XBZ
*O QSFWJPVT DIBQUFST XFƊWF DPWFSFE XBZT PG VTJOH Maybe
Either BOE Validation UZQFT UP IBOEMF DFSUBJO FSSPS DPOEJUJPOT
FYQMJDJUMZ 3BJTJOH FYDFQUJPOBM DPOEJUJPOT WJB TVDI EBUBUZQFT
JTOƊU BMXBZT JEFBM IPXFWFS *O TPNF DBTFT FYDFQUJPOT DBO
CF GBTUFS CZ FMJEJOH SFQFBUFE DIFDLT GPS BO BEWFSTF DPOEJUJPO
&YDFQUJPOT BSF OPU FYQMJDJUMZ QBSU PG UIF JOUFSGBDFT ZPVƊSF VTJOH
BOE UIBU IBT JNNFEJBUF DPOTFRVFODFT XIFO USZJOH UP SFBTPO
BCPVU UIF XBZT JO XIJDI ZPVS QSPHSBN DPVME GBJM
-FUUJOH FYDFQUJPOT BSJTF BT UIFZ XJMM ƈ BOE UIF QSPHSBN
IBMU XJMMZOJMMZ ƈ JT TVCPQUJNBM &YDFQUJPO IBOEMJOH JT B XBZ
PG EFBMJOH XJUI FSSPST BOE HJWJOH UIF QSPHSBN TPNF BMUFSOBUF
NFBOT PG FYFDVUJPO PS UFSNJOBUJPO TIPVME POF BSJTF 5IJT
DIBQUFS JT HPJOH UP DPWFS CPUI FYDFQUJPOT BOE XIBU UIFZ MPPL
MJLF BT XFMM BT WBSJPVT NFBOT PG IBOEMJOH UIFN
*O UIJT DIBQUFS XF XJMM
$)"15&3  8)&/ 5)*/(4 (0 830/( 

Ƒ FYBNJOF UIF Exception UZQFDMBTT BOE NFUIPET

Ƒ EJQ PVS UPFT JOUP FYJTUFOUJBM RVBOUJƶDBUJPO

Ƒ EJTDVTT XBZT PG IBOEMJOH FYDFQUJPOT

 5IF &YDFQUJPO DMBTT BOE NFUIPET


&YDFQUJPOT BSF QMBJO PME UZQFT BOE WBMVFT MJLF ZPVƊWF TFFO
UISPVHIPVU UIF CPPL 5IF UZQFT UIBU FODPEF FYDFQUJPOT NVTU
IBWF BO JOTUBODF PG UIF &YDFQUJPO UZQFDMBTT 5IF PSJHJOT PG
FYDFQUJPOT BT UIFZ FYJTU JO )BTLFMM UPEBZ BSF JO 4JNPO .BS
MPXƊT XPSL PO BO FYUFOTJCMF IJFSBSDIZ PG FYDFQUJPOT XIJDI
BSF EJTDSJNJOBUFE BU SVOUJNF 6TJOH UIJT FYUFOTJCMF IJFSBSDIZ
BMMPXT ZPV UP CPUI DBUDI FYDFQUJPOT UIBU NBZ IBWF WBSJPVT
UZQFT BOE BMTP BEE OFX FYDFQUJPO UZQFT BT UIF OFFE BSJTFT
5IF &YDFQUJPO UZQFDMBTT EFƶOJUJPO MPPLT MJLF UIJT

class (Typeable e, Show e) =>


Exception e where
toException :: e -> SomeException
fromException :: SomeException -> Maybe e
displayException :: e -> String
-- Defined in ‘GHC.Exception’

http://community.haskell.org/~simonmar/papers/ext-exceptions.pdf
$)"15&3  8)&/ 5)*/(4 (0 830/( 

8FƊMM UBLF B MPPL BU UIPTF NFUIPET JO B NPNFOU 5IF Show


DPOTUSBJOU JT UIFSF TP UIBU XF DBO QSJOU UIF FYDFQUJPO UP UIF
TDSFFO JO B SFBEBCMF GPSN GPS XIBUFWFS UZQF F FOET VQ CFJOH
Typeable JT B UZQFDMBTT UIBU EFƶOFT NFUIPET PG JEFOUJGZJOH UZQFT
BU SVOUJNF 8F XJMM UBML BCPVU UIJT NPSF BOE FYQMBJO XIZ UIFTF
DPOTUSBJOUT BSF OFDFTTBSZ UP PVS Exception DMBTT TPPO
5IF MJTU PG UZQFT UIBU IBWF BO Exception JOTUBODF JT MPOH

-- some instances elided


instance Exception IOException
instance Exception Deadlock
instance Exception BlockedIndefinitelyOnSTM
instance Exception BlockedIndefinitelyOnMVar
instance Exception AsyncException
instance Exception AssertionFailed
instance Exception AllocationLimitExceeded
instance Exception SomeException
instance Exception ErrorCall
instance Exception ArithException

8F XPOƊU UBML JO EFUBJM BCPVU FBDI PG UIFTF CVU ZPV NBZ CF


BCMF UP ƶHVSF PVU XIBU GPS FYBNQMF BlockedIndefinitelyOnMVar
JT VTFE GPS 8FƊMM OPUF UIBU JUƊT TJNQMZ B EBUBUZQF XJUI POF
JOIBCJUBOU
$)"15&3  8)&/ 5)*/(4 (0 830/( 

data BlockedIndefinitelyOnMVar =
BlockedIndefinitelyOnMVar
-- Defined in ‘GHC.IO.Exception’

*G XF MPPL BU ArithException XFƊMM ƶOE UIBU JUƊT B TVN UZQF


XJUI TFWFSBM WBMVFT

data ArithException
= Overflow
| Underflow
| LossOfPrecision
| DivideByZero
| Denormal
| RatioZeroDenominator

instance Exception ArithException

*G ZPV JNQPSU UIF Control.Exception NPEVMF ZPV DBO QPLF


BU ArithExceptionƊT EBUB DPOTUSVDUPST BOE TFF UIBU UIFZƊSF QMBJO
PME WBMVFT OPUIJOH VOVTVBM BU BMM

#VU UIFSF JT TPNFUIJOH EJƵFSFOU HPJOH PO IFSF


8FƊSF HPJOH UP TUBSU VOQBDLJOH BMM UIJT UP TFF IPX UIF QBSUT
XPSL UPHFUIFS 'JSTU MFUƊT UBLF B MPPL BU UIF NFUIPET PG UIF
Exception UZQFDMBTT
$)"15&3  8)&/ 5)*/(4 (0 830/( 

toException :: e -> SomeException


fromException :: SomeException -> Maybe e

8F EPOƊU IBWF NVDI PDDBTJPO UP VTF UIF toException BOE


fromException GVODUJPOT UIFNTFMWFT *OTUFBE XF VTF PUIFS GVOD
UJPOT UIBU DBMM UIFN GPS VT "T JU UVSOT PVU UIF toException
NFUIPE JT RVJUF TJNJMBS UP UIF EBUB DPOTUSVDUPS GPS SomeException
:PV NBZ IBWF OPUJDFE UIBU SomeException JT BMTP B UZQF UIBU JT
MJTUFE BT IBWJOH BO JOTUBODF PG UIF Exception UZQFDMBTT BOE OPX
IFSF JU JT JO UIF Exception NFUIPET *U TFFNT B CJU DJSDVMBS CVU
JU UVSOT PVU UIBU SomeException JT VMUJNBUFMZ UIF LFZ UP UIF XBZ
XF IBOEMF FYDFQUJPOT

" CSJFG JOUSPEVDUJPO UP FYJTUFOUJBM RVBOUJƶDBUJPO


SomeException BDUT BT B TPSU PG QBSFOU UZQF GPS BMM UIF PUIFS FY
DFQUJPO UZQFT TP UIBU XF DBO IBOEMF NBOZ FYDFQUJPO UZQFT BU
PODF XJUIPVU IBWJOH UP NBUDI BMM PG UIFN -FUƊT FYBNJOF IPX

data SomeException where


SomeException :: Exception e => e -> SomeException

5IJT NBZ OPU TFFN PEE BU ƶSTU HMBODF 5IBU JT EVF JO QBSU
UP UIF GBDU UIBU UIF XFJSEOFTT JT IJEJOH JO B DPOTUSVDUJPO DBMMFE
B ("%5 GPS HFOFSBMJ[FE BMHFCSBJD EBUBUZQF 'PS UIF NPTU
QBSU ("%5T BSF PVU PG UIF TDPQF PG UIJT CPPL CFJOH XFMM
JOUP JOUFSNFEJBUF )BTLFMM UFSSJUPSZ UIBU JT GVO UP FYQMPSF CVU
$)"15&3  8)&/ 5)*/(4 (0 830/( 

OPU TUSJDUMZ OFDFTTBSZ UP QSPHSBNNJOH JO )BTLFMM 8IBU UIF


("%5 TZOUBY JT IJEJOH UIFSF JT TPNFUIJOH DBMMFE FYJTUFOUJBM
RVBOUJƶDBUJPO
8F DPVME SFXSJUF UIF SomeException UZQF MJLF UIJT XJUIPVU B
DIBOHF JO NFBOJOH

data SomeException =
forall e . Exception e => SomeException e

0SEJOBSJMZ UIF forall RVBOUJƶFT WBSJBCMFT VOJWFSTBMMZ BT


ZPV NJHIU HVFTT GSPN UIF XPSE BMM )PXFWFS UIF SomeException
UZQF DPOTUSVDUPS EPFTOƊU UBLF BO BSHVNFOU UIF UZQF WBSJBCMF F
JT B QBSBNFUFS PG UIF EBUB DPOTUSVDUPS *U UBLFT BO F BOE SFTVMUT JO
B SomeException .PWJOH UIF RVBOUJƶFS UP UIF EBUB DPOTUSVDUPS
MJNJUT UIF TDPQF PG JUT BQQMJDBUJPO BOE DIBOHFT UIF NFBOJOH
GSPN ƌGPS BMM Fƍ UP ƌUIFSF FYJTUT TPNF Fƍ 5IBU JT FYJTUFOUJBM RVBO
UJƶDBUJPO *U NFBOT UIBU BOZ UZQF UIBU JNQMFNFOUT UIF Exception
DMBTT DBO CF UIBU F BOE CF TVCTVNFE VOEFS UIF SomeException
UZQF
8F BSFOƊU HPJOH UP FYBNJOF FYJTUFOUJBM RVBOUJƶDBUJPO EFFQMZ
IFSF UIJT JT B NFSF UBTUF 6TVBMMZ XIFO UZQF DPOTUSVDUPST BSF
QBSBNFUFSJ[FE UIFZ BSF VOJWFSTBMMZ RVBOUJƶFE "SHVNFOUT
IBWF UP CF TVQQMJFE UP TBUJTGZ UIFN :PVS Maybe a UZQF JT BT
XFƊWF OPUFE CFGPSF B TPSU PG GVODUJPO XBJUJOH GPS BO BSHVNFOU
UP CF TVQQMJFE UP CF B GVMMZ SFBMJ[FE UZQF
$)"15&3  8)&/ 5)*/(4 (0 830/( 

#VU XIFO XF FYJTUFOUJBMMZ RVBOUJGZ B UZQF BT XJUI SomeException


XF DBOƊU EP NVDI XJUI UIBU QPMZNPSQIJD UZQF WBSJBCMF JO JUT
EBUB DPOTUSVDUPS 8F DBOƊU DPODSFUJ[F JU 0UIFS UIBO BEEJOH
DPOTUSBJOUT XF DBOƊU LOPX BOZUIJOH BCPVU JU *U NVTU SFNBJO
QPMZNPSQIJD BOE XF DBO DSBN BOZ WBMVF PG BOZ UZQF UIBU JN
QMFNFOUT JUT DPOTUSBJOU JOUP UIBU SPMF *UƊT MJLF B QPMZNPSQIJD
QBSBTJUF KVTU IBOHJOH PVU PO ZPVS UZQF
4P BOZ FYDFQUJPO UZQF ƈ BOZ UZQF XJUI BO JOTUBODF PG
UIF &YDFQUJPO UZQFDMBTT ƈ DBO CF UIBU F BOE CF IBOEMFE BT B
SomeException 8F OFFE Typeable BOE Show JO PSEFS UP EFUFSNJOF
XIBU UZQF PG FYDFQUJPO XFƊSF EFBMJOH XJUI BT XF XJMM TPPO TFF

4P XBJU XIBU
'PS BO FYBNQMF PG XIBU FYJTUFOUJBM RVBOUJƶDBUJPO MFUT VT EP
XFƊSF HPJOH UP TIPX ZPV BO FYBNQMF UIBU EPFTOƊU SFMZ PO UIF
NBHJD PG UIF SVOUJNF FYDFQUJPO NBDIJOFSZ )FSF XFƊMM CF
SFUVSOJOH FSSPST JO Either PG UPUBMMZ EJƵFSFOU UZQFT XJUIPVU
IBWJOH UP VOJGZ UIFN VOEFS B TJOHMF TVN UZQF
$)"15&3  8)&/ 5)*/(4 (0 830/( 

{-# LANGUAGE ExistentialQuantification #-}


{-# LANGUAGE GADTs #-}

module WhySomeException where

import Control.Exception (ArithException(..)


, AsyncException(..))
import Data.Typeable

data MyException =
forall e .
(Show e, Typeable e) => MyException e

instance Show MyException where


showsPrec p (MyException e) =
showsPrec p e

multiError :: Int
-> Either MyException Int
multiError n =
case n of
0 ->
Left (MyException DivideByZero)
1 ->
Left (MyException StackOverflow)
_ -> Right n
$)"15&3  8)&/ 5)*/(4 (0 830/( 

8IBUƊT TQFDJBM BCPVU UIF BCPWF JT UIBU XF IBWF B Left DBTF


JO PVS Either UIBU JODMVEFT FSSPS WBMVFT PG UXP UPUBMMZ EJƵFSFOU
UZQFT XJUIPVU FOVNFSBUJOH UIFN JO B TVN UZQF MyException
EPFTOƊU BQQFBS UP IBWF B QPMZNPSQIJD BSHVNFOU JO UIF UZQF
DPOTUSVDUPS CVU JU EPFT JO UIF EBUB DPOTUSVDUPS 8F BSF BCMF
UP BQQMZ UIF MyException EBUB DPOTUSVDUPS UP WBMVFT PG EJƵFSFOU
UZQFT CFDBVTF PG UIF FYJTUFOUJBMMZ RVBOUJƶFE UZQF GPS Ԕ

data SomeError =
Arith ArithException
| Async AsyncException
| SomethingElse
deriving (Show)

discriminateError :: MyException
-> SomeError
discriminateError (MyException e) =
case cast e of
(Just arith) -> Arith arith
Nothing ->
case cast e of
(Just async) -> Async async
Nothing -> SomethingElse
$)"15&3  8)&/ 5)*/(4 (0 830/( 

runDisc n =
either discriminateError
(const SomethingElse) (multiError n)

5IFO USZJOH UIJT PVU

Prelude> runDisc 0
Arith divide by zero
Prelude> runDisc 1
Async stack overflow
Prelude> runDisc 2
SomethingElse

5IJT JT UIF FTTFODF PG XIZ XF OFFE FYJTUFOUJBM RVBOUJƶDBUJPO


GPS FYDFQUJPOT ƈ TP UIBU XF DBO UISPX WBSJPVT FYDFQUJPO UZQFT
XJUIPVU CFJOH GPSDFE UP DFOUSBMJ[F BOE VOJGZ UIFN VOEFS B
TVN UZQF %POƊU BCVTF UIJT GBDJMJUZ
1SJPS UP UIJT EFTJHO UIFSF XFSF B GFX XBZT ZPV DPVME EP
FYDFQUJPO IBOEMJOH 4PNF PG UIF NPSF BQQBSFOU NFUIPET
XPVMEƊWF CFFO POF CJH TVN UZQF PS TUSJOHT 5IF QSPCMFN JT
UIBU OFJUIFS PG UIFN BSF NFBOJOHGVMMZ FYUFOTJCMF UP TUSVDUVSFE
QSPQFS EBUB UZQFT 8F XBOU JO B TFOTF B IJFSBSDIZ PG WBMVFT
XIFSF DBUDIJOH B ƌQBSFOUƍ NFBOT DBUDIJOH BOZ PG UIF QPTTJCMF
ƌDIJMESFOƍ 5IF DPNCJOBUJPO PG SomeException BOE UIF Typeable
UZQFDMBTT HJWFT ZPV B NFBOT PG UISPXJOH EJƵFSFOU FYDFQUJPOT
PG EJƵFSFOU UZQFT BOE UIFO DBUDIJOH TPNF PS BMM PG UIFN JO B
IBOEMFS XJUIPVU XSBQQJOH UIFN JO B TVN UZQF
$)"15&3  8)&/ 5)*/(4 (0 830/( 

5ZQFBCMF
5IF Typeable UZQFDMBTT MJWFT JO UIF Data.Typeable MJCSBSZ Typeable
FYJTUT UP QFSNJU UZQFT UP CF LOPXO BU SVOUJNF BMMPXJOH GPS B
TPSU PG EZOBNJD UZQFDIFDLJOH *U BMMPXT ZPV UP MFBSO UIF UZQF
PG B WBMVF BU SVOUJNF BOE BMTP UP DPNQBSF UIF UZQFT PG UXP WBM
VFT BOE DIFDL UIBU UIFZ BSF UIF TBNF 5ZQFBCMF JT QBSUJDVBSMZ
VTFGVM XIFO ZPV IBWF DPEF UIBU OFFET UP BMMPX WBSJPVT UZQFT
UP CF QBTTFE UP JU CVU OFFET UP FOGPSDF PS USJHHFS PO TQFDJƶD
UZQFT
5IJT JT PSEJOBSJMZ VOXJTF BT B HFOFSBM QBUUFSO CVU JU NBLFT
TFOTF XIFO ZPVƊSF UBMLJOH BCPVU FYDFQUJPOT 8IFO XFƊSF DPO
DFSOFE XJUI FYDFQUJPO IBOEMJOH XF XBOU UP CF BCMF UP DIFDL
XIFUIFS WBMVFT PG QPTTJCMZ WBSZJOH UZQFT NBUDI UIF &YDFQUJPO
UZQF XFƊSF USZJOH UP IBOEMF BOE XF OFFE UP EP UIBU BU SVOUJNF
XIFO UIF FYDFQUJPO PDDVST 5IVT XF OFFE UIJT SVOUJNF XJUOFTT
UP UIF UZQFT PG UIF FYDFQUJPOT
5ZQFBCMF IBT POF NFUIPE

cast :: (Typeable a, Typeable b) => a -> Maybe b

*U UVSOT PVU XF EPOƊU VTVBMMZ DBMM UIJT GVODUJPO EJSFDUMZ FJ


UIFS CVU JU HFUT DBMMFE GPS VT CZ UIF fromException GVODUJPO BOE
fromException JT DBMMFE CZ UIF catch GVODUJPO
"U SVOUJNF XIFO BO FYDFQUJPO JT UISPXO JU TUBSUT SPMMJOH
CBDL UISPVHI UIF TUBDL MPPLJOH GPS B catch 8IFO JU ƶOET B
catch JU DIFDLT UP TFF XIBU UZQF PG FYDFQUJPO UIJT catch DBUDIFT
$)"15&3  8)&/ 5)*/(4 (0 830/( 

*U DBMMT fromException BOE cast UP DIFDL JG UIF UZQF PG UIF FYDFQ


UJPO UIBU HPU UISPXO NBUDIFT UIF UZQF PG BO FYDFQUJPO XFƊSF
IBOEMJOH XJUI UIF catch " catch UIBU IBOEMFT B SomeException
XJMM NBUDI BOZ UZQF PG FYDFQUJPO EVF UP UIF ƷFYJCJMJUZ PG UIBU
UZQF
*G UIFZ EPOƊU NBUDI XF HFU B Nothing WBMVF UIF FYDFQUJPO
XJMM LFFQ SPMMJOH VQ UISPVHI UIF TUBDL MPPLJOH GPS B catch UIBU
DBO IBOEMF UIF FYDFQUJPO UIBU XBT UISPXO *G JU EPFTOƊU ƶOE
POF ZPVS QSPHSBN KVTU EJFT BO VOTFFNMZ EFBUI
*G UIFZ EP NBUDI UIF Just a BMMPXT VT UP DBUDI UIF FYDFQUJPO

 5IJT NBDIJOF LJMMT QSPHSBNT


&YDFQUJPOT DBO CF UISPXO JO QVSF DPEF

Prelude> 2 `div` 0
*** Exception: divide by zero

)PXFWFS main JT BMXBZT BO IO BDUJPO TP NPTU PG UIF UJNF


XIFO ZPV OFFE UP XPSSZ BCPVU FYDFQUJPOT ZPVƊMM CF JO IO
&WFO XIFO UIFZ IBQQFO JO QVSF DPEF FYDFQUJPOT NBZ POMZ
CF DBVHIU PS IBOEMFE JO IO
IO DPOUBJOT UIF JNQMJDJU DPOUSBDU ƌ:PV DBOOPU FYQFDU UIJT
DPNQVUBUJPO UP TVDDFFE VODPOEJUJPOBMMZƍ *U UVSOT PVU UIF
PVUTJEF XPSME JT B IBSTI NJTUSFTT ƈ KVTU BCPVU BOZ IO BDUJPO
DBO GBJM FWFO putStrLn
$)"15&3  8)&/ 5)*/(4 (0 830/( 

'JSTU MFUƊT EFNPOTUSBUF UIBU BOZ IO BDUJPO DBO GBJM 8F XJMM


BTTVNF UIBU ZPV EP OPU DVSSFOUMZ IBWF B ƶMF DBMMFE aaa JO ZPVS
XPSLJOH EJSFDUPSZ 4P XIFO ZPV SVO UIJT DPEF JU XJMM DSFBUF
UIF ƶMF XSJUF UP JU QSJOU ƌXSPUF UP ƶMFƍ JO ZPVS UFSNJOBM BOE
UFSNJOBUF TVDDFTTGVMMZ

-- writePls.hs
module Main where

main = do
writeFile "aaa" "hi"
putStrLn "wrote to file"

:PV DBO ƶSF VQ ZPVS 3&1- BOE MPBE UIBU PS ZPV DBO DPNQJMF
UIF CJOBSZ MJLF UIJT UIJT JT SFWJFX TP JG ZPV BMSFBEZ IBWF BMM
UIJT EPXO UIFO HP BIFBE BOE EP JU


stack ghc -- <filename> -o <output file name>

"OE SVO JU MJLF UIJT

$ ./<output file name>

4P JG ZPV DBMMFE UIF PVUQVU ƶMF wp GPS FYBNQMF ZPVS UFSNJ


OBM TFTTJPO NJHIU MPPL MJLF UIJT

$ stack ghc -- writepls.hs -o wp


[stack compilation messages]
$)"15&3  8)&/ 5)*/(4 (0 830/( 

$ ./wp
wrote to file
$ cat aaa
hi

$PPM UIBU BMM XPSLFE 5IBU XPSLFE JO QBSU CFDBVTF writeFile


XJMM HP BIFBE BOE DSFBUF B ƶMF BOE HJWF JU XSJUF QFSNJTTJPOT
JG UIF ƶMF ZPVƊSF USZJOH UP XSJUF UP EPFT OPU FYJTU #VU XIBU JG
ZPVƊSF USZJOH UP XSJUF UP B ƶMF UIBU EPFT BMSFBEZ FYJTU BOE EPFT
OPU IBWF XSJUF QFSNJTTJPOT
.BLF B SFBEPOMZ ƶMF OBNFE zzz UIBU XF DBO FYQFSJNFOU
XJUI 5P NBLF B ƶMF UIBU DBOOPU CF XSJUUFO UP PO -JOVY PS .BD
UIF GPMMPXJOH TVƸDFT

$ touch zzz
$ chmod 400 zzz

4VQQPTF UIBU ƶMF DPIBCJUT B EJSFDUPSZ XIFSF XFƊSF USZJOH UP


FYFDVUF UIJT QSPHSBN

-- writePls.hs
module Main where

main = do
writeFile "zzz" "hi"
putStrLn "wrote to file"
$)"15&3  8)&/ 5)*/(4 (0 830/( 

*UƊT UIF TBNF QSPHSBN XF IBE GPS UIF aaa ƶMF KVTU XJUI UIF
ƶMF OBNF DIBOHFE :PV DBO ƶSF VQ ZPVS 3&1- BOE MPBE UIBU
PS ZPV DBO DPNQJMF UIF CJOBSZ BT XF EJE BCPWF
5IFO JG ZPV SVO UIJT QSPHSBN XJUI TVDI B ƶMF ZPVƊMM HFU UIF
GPMMPXJOH SFTVMU

$ ./wp
wp: zzz: openFile: permission denied (Permission denied)

5IFSFƊT B IPMF JO PVS CVDLFU EFBS -J[B BO FYDFQUJPO

$BUDI NF JG ZPV DBO


-FUƊT ƶY UIBU EFBS )FOSZ 8FƊMM TUBSU XJUI TPNF SVEJNFOUBSZ
FYDFQUJPO IBOEMJOH
$)"15&3  8)&/ 5)*/(4 (0 830/( 

module Main where

import Control.Exception
import Data.Typeable

handler :: SomeException -> IO ()


handler (SomeException e) = do
print (typeOf e)
putStrLn ("We errored! It was: " ++ show e)

main =
writeFile "zzz" "hi"
`catch` handler

8FƊSF TUJMM HPJOH UP UFSNJOBUF XJUIPVU XSJUJOH UP UIF ƶMF GPS


UIF TBNF SFBTPOT BT BCPWF 5IF QSPHSBN XJMM SVO BOE UFSNJ
OBUF TVDDFTTGVMMZ CVU JUƊMM NFOUJPO UIF FSSPS BOE TBZ UIBU JU
GBJMFE XJUI BO IOException 8FƊMM HFU B CJU NPSF JOGPSNBUJPO
BCPVU XIZ UIF QSPHSBN GBJMFE BOE CF BCMF UP MPH UIBU JOGPSNB
UJPO XJUI PVS FYDFQUJPO IBOEMFS JG XF XJTI 4PNFUJNFT UIBUƊT
FYBDUMZ XIBU ZPV XBOU GPS ZPVS QSPHSBN UP MPH UIF FYDFQUJPO
BOE UIFO EJF 4PPO XFƊMM MPPL BU TPNF PUIFS PQUJPOT GPS IBO
EMJOH FYDFQUJPOT JO B XBZ UIBU MFUT ZPVS QSPHSBN QSPDFFE XJUI
BO BMUFSOBUF FYFDVUJPO
'PS OPX MFUƊT UVSO PVS BUUFOUJPO UP catch
$)"15&3  8)&/ 5)*/(4 (0 830/( 

catch :: Exception e => IO a -> (e -> IO a) -> IO a

:PV NBZ SFDBMM XF NFOUJPOFE catch FBSMJFS CFDBVTF JU DBMMT


fromException BOE cast GPS VT *U SVOT POMZ JG UIF FYDFQUJPO
NBUDIJOH UIF UZQF ZPV TQFDJƶFE HFUT UISPXO BOE JU HJWFT ZPV
BO PQQPSUVOJUJUZ UP SFDPWFS GSPN UIF FSSPS BOE TUJMM TBUJTGZ
UIF PSJHJOBM UZQF UIBU ZPVS IO BDUJPO QVSQPSUFE UP CF *G OP
FYDFQUJPO HFUT UISPXO UIFO OPUIJOH IBQQFOT XJUI UIBU F BOE
UIF IO a BU UIF GSPOU JT UIF TBNF BT UIF IO a BU UIF FOE
-FUƊT FYQBOE PVS SVEJNFOUBSZ FSSPS IBOEMJOH JO B XBZ UIBU
BMMPXT UIF QSPHSBN BO BMUFSOBUF FYFDVUJPO NFUIPE JOTUFBE
PG BMMPXJOH JU UP EJF 5IJT UJNF UIF main BDUJPO TUJMM XBOUT UP
XSJUF UP UIBU SFBEPOMZ ƶMF CVU UIJT UJNF PVS IBOEMFS HJWFT
JU BO BMUFSOBUF ƶMF UIBU EPFT OPU FYJTU UP XSJUF UP JG ZPV EP
IBWF B ƶMF DBMMFE bbb JO ZPVS QSFTFOU XPSLJOH EJSFDUPSZ ZPV
DBO DIBOHF UIF OBNF PG UIF writeFile BSHVNFOU UP TPNF PUIFS
OBNF BOZUIJOH BT MPOH BT JU EPFTOƊU FYJTU JO ZPVS EJSFDUPSZ
ZFU

$)"15&3  8)&/ 5)*/(4 (0 830/( 

-- writePls.hs
module Main where

import Control.Exception
import Data.Typeable

handler :: SomeException -> IO ()


handler (SomeException e) = do
putStrLn ("Running main caused an error! It was: "
++ show e)
writeFile "bbb" "hi"

main =
writeFile "zzz" "hi"
`catch` handler

8IFO XSJUJOH UP zzz GBJMT JU TIPVME QSJOU UIF FSSPS NFTTBHF


UP UIF UFSNJOBM *G ZPV DIFDL ZPVS EJSFDUPSZ ZPV TIPVME TFF
ZPVS BMUFSOBUF ƶMF OBNFE JO UIF IBOEMFS GVODUJPO BOE JG ZPV
MPPL JOTJEF UIBU JU TIPVME TBZ ƌIJƍ UP ZPV
-FUƊT MPPL BU BOPUIFS TMJHIUMZ NPSF DPNQMFY VTF PG catch
5IJT JT UBLFO GSPN B QSPHSBN UIBU EFMFUFT UIJOHT GSPN B 5XJUUFS
BDDPVOU BOE SFMJFT PO UIF MJCSBSZ twitter-conduit 5IJT QPSUJPO
PG UIF QSPHSBN DBO GBJM XIFO JU EPFTOƊU IBWF BDDFTT UP UIF

https://www.stackage.org/package/twitter-conduit
$)"15&3  8)&/ 5)*/(4 (0 830/( 

BQQSPQSJBUF DSFEFOUJBMT GPS UBMLJOH UP B 5XJUUFS BDDPVOU 4P


XF CVJMU BO FYDFQUJPO IBOEMFS UIBU UFMMT JU XIBU UP EP XIFO UIBU
FYDFQUJPO BSJTFT

withCredentials action = do
twinfo <- loadCredentials `catch` handleMissing
case twinfo of
Nothing -> getTWInfo >>= saveCredentials
Just twinfo -> action twinfo
where handleMissing :: IOException
-> IO (Maybe TWInfo)
handleMissing _ = return Nothing

8F UVSO BO IOException JOUP BO IO (Maybe a) TP XF DBO DBTF


PO UIF Maybe UP UFMM JU XIBU UP EP JO UIF Nothing DBTF *O UIJT
DBTF JG XF UISPX BO IOException BOE SFUVSO B Nothing WBMVF PVS
QSPHSBN XJMM FYFDVUF UIJT

getTWInfo >>= saveCredentials

#Z TBWJOH UIF DSFEFOUJBMT UIF DPEF UIBU BDUVBMMZ EPFT UIF


TBWJOH JT OPU TIPXO IFSF
XF IPQFGVMMZ XPOƊU FODPVOUFS UIJT
FYDFQUJPO UIF OFYU UJNF XF USZ UP SVO JU *O XIJDI DBTF XF
QFSGPSN UIF action UIBU JT OBNFE JO UIF Just twinfo MJOF TBJE
BDUJPO JT BMTP OPU TIPXO IFSF TPSSZ

$)"15&3  8)&/ 5)*/(4 (0 830/( 

 8BOU FJUIFS 5SZ


4PNFUJNFT XFƊE MJLF UP MJǒ FYDFQUJPOT PVU JOUP FYQMJDJU Either
WBMVFT 5IJT JT RVJUF EPBCMF CVU ZPV DBOƊU FSBTF UIF GBDU UIBU
ZPV QFSGPSNFE *0 JO UIF QSPDFTT *UƊT BMTP OP HVBSBOUFF ZPVƊMM
DBUDI BMM FYDFQUJPOT )FSFƊT UIF GVODUJPO XF OFFE UP UVSO JN
QMJDJU FYDFQUJPOT JOUP BO FYQMJDJU Either

-- Control.Exception
try :: Exception e => IO a -> IO (Either e a)

5IFO UP VTF JU XF DPVME XSJUF TPNFUIJOH MJLF UIF GPMMPXJOH


DPEF QMFBTF OPUF UIJT XJMM OPU DPNQJMF UP B CJOBSZ UIF XBZ
FBSMJFS FYBNQMFT EJE CFDBVTF JU JT OPU B Main FYFDVUBCMF KVTU
VTF ()$J


module TryExcept where

import Control.Exception

willIFail :: Integer
-> IO (Either ArithException ())
willIFail denom =
try $ print $ div 5 denom
$)"15&3  8)&/ 5)*/(4 (0 830/( 

)FSF XF QSJOU UIF SFTVMU CFDBVTF ZPV DBO POMZ IBOEMF FY
DFQUJPOT JO IO FWJEFODFE CZ UIF UZQFT PG try BOE catch *G ZPV
GFFE UIJT TPNF JOQVUT ZPVƊMM TFF TPNFUIJOH MJLF UIF GPMMPXJOH

Prelude> willIFail 1
5
Right ()
Prelude> willIFail 0
Left divide by zero

0OF UIJOH UP LFFQ JO NJOE JT UIBU FYDFQUJPOT JO )BTLFMM BSF


MJLF FYDFQUJPOT JO NPTU PUIFS QSPHSBNNJOH MBOHVBHFT ƈ UIFZ
BSF JNQSFDJTF "O FYDFQUJPO OPU DBVHIU CZ B QBSUJDVMBS CJU PG
DPEF XJMM HFU SPMMFE VQ CZ UIF FYDFQUJPO VOUJM JUƊT FJUIFS DBVHIU
PS LJMMT ZPVS QSPHSBN
*G ZPV XBOUFE UP HFU SJE PG UIF Right () UIBU JUƊT QSJOUJOH JO
UIF TVDDFTTGVM DBTFT IFSFƊT POF XBZ UP HFU SJE PG JU
$)"15&3  8)&/ 5)*/(4 (0 830/( 

onlyReportError :: Show e
=> IO (Either e a)
-> IO ()
onlyReportError action = do
result <- action
case result of
Left e -> print e
Right _ -> return ()

willFail :: Integer -> IO ()


willFail denom =
onlyReportError $ willIFail denom

0S ZPV DPVME VTF catch

willIFail' :: Integer -> IO ()


willIFail' denom =
print (div 5 denom) `catch` handler
where handler :: ArithException
-> IO ()
handler e = print e

-FUƊT FYQBOE PO UIJT 8F XBOU UP UBLF UIF BCPWF FYBNQMFT


BOE UVSO UIFN JOUP BO FYFDVUBCMF CJOBSZ XIJDI JT B QSPCMFN
CFDBVTF JO BO FYFDVUBCMF main DBOƊU UBLF BSHVNFOUT 4P XFƊMM
IBWF UP EP TPNF TFSJPVT NPEJƶDBUJPO JO PSEFS UP CF BCMF UP
$)"15&3  8)&/ 5)*/(4 (0 830/( 

QBTT BSHVNFOUT UP main XIFO XF DBMM JU 8FƊSF HPJOH UP JNQPSU


System.Environment TP UIBU XF DBO NBLF VTF PG B GVODUJPO DBMMFE
getArgs UIBU BMMPXT VT UP QBTT BSHVNFOUT JO BU UIF QPJOU XIFSF
XF DBMM main

module Main where

import Control.Exception
import System.Environment (getArgs)

willIFail :: Integer
-> IO (Either ArithException ())
willIFail denom =
try $ print $ div 5 denom

onlyReportError :: Show e
=> IO (Either e a)
-> IO ()
onlyReportError action = do
result <- action
case result of
Left e -> print e
Right _ -> return ()
$)"15&3  8)&/ 5)*/(4 (0 830/( 

testDiv :: String -> IO ()


testDiv d =
onlyReportError $ willIFail (read d)

main :: IO ()
main = do
args <- getArgs
mapM_ testDiv args

5IF VTF PG mapM_ IFSF NJHIU OPU CF PCWJPVT TP MFUƊT VOQBDL


UIBU B CJU *U JT FTTFOUJBMMZ B MFTT HFOFSBM traverse GVODUJPO UIBU
UISPXT BXBZ JUT FOE SFTVMU BOE POMZ QSPEVDFT UIF FƵFDUT *O UIJT
DBTF UIPTF FƵFDUT BSF HPJOH UP CF UIF SFTVMUT PG NBQQJOH PVS
testDiv GVODUJPO PWFS B MJTU PG BSHVNFOUT ƈ SFUVSOJOH FJUIFS
UIF SFTVMU PG B TVDDFTTGVM EJWJTJPO PS UIF UZQF PG BO FYDFQUJPO
8FƊMM DPNQJMF UIJT POF UP BO FYFDVUBCMF CJOBSZ BHBJO BT XF
EJE FBSMJFS JO UIF DIBQUFS 5P QBTT JO UIF BSHVNFOUT JU XJMM
MPPL MJLF UIJT

$ stack ghc -- writepls.hs -o wp


[stack noise]
$ ./wp 4 5 0 9
1
1
divide by zero
0
$)"15&3  8)&/ 5)*/(4 (0 830/( 

*O DBTF ZPV XBOUFE UP USZ UIJT JO UIF 3&1- SFQSPEVDJOH


XIBU ZPV EJE BCPWF VTF UIF :main ()$J DPNNBOE BOE QBTT
UIF TBNF BSHVNFOUT

Prelude> :main 4 5 0 9
1
1
divide by zero
0

/PUJDF UIBU OPX UIBU UIF FYDFQUJPO JT IBOEMFE XF DBO TUJMM


HFU UIBU MBTU SFTVMU ƈ XF IBWF TVSWJWFE BO ArithException

 5IF VOCFBSBCMF JNQSFDJTJPO PG


USZJOH
-FUƊT EP BOPUIFS MJUUMF FYQFSJNFOU

import Control.Exception

canICatch :: Exception e
=> e
-> IO (Either ArithException ())
canICatch e =
try $ throwIO e
$)"15&3  8)&/ 5)*/(4 (0 830/( 

5IF OFX UIJOH IFSF JT throwIO B GVODUJPO UIBU BMMPXT ZPV


UP UISPX BO FYDFQUJPO 3JHIU OPX XF XBOU UP EFNPOTUSBUF
UIBU UIJT IBOEMFS EPFTOƊU DBUDI BMM UZQFT PG FYDFQUJPOT TP XFƊSF
VTJOH throwIO UP DBVTF FYDFQUJPOT PG WBSJPVT UZQFT UP CF UISPXO
5IF Left IFSF DBO POMZ IBOEMF PS DBUDI BO ArithException
OPU BOZ PUIFS LJOE 4P XIFO XF UISPX B EJƵFSFOU UZQF PG
FYDFQUJPO XF HFU UIF GPMMPXJOH

Prelude> canICatch DivideByZero


Left divide by zero
Prelude> canICatch StackOverflow
*** Exception: stack overflow
Prelude> :t DivideByZero
DivideByZero :: ArithException
Prelude> :t StackOverflow
StackOverflow :: AsyncException

5IF MBUUFS DBTF CMFX QBTU PVS try CFDBVTF XF XFSF USZJOH UP
DBUDI BO "SJUI&YDFQUJPO OPU BO "TZOD&YDFQUJPO
8FƊWF NFOUJPOFE TFWFSBM UJNFT UIBU SomeException XJMM NBUDI
PO BMM UZQFT UIBU JNQMFNFOU UIF Exception UZQFDMBTT TP USZ
SFXSJUJOH UIF BCPWF TVDI UIBU UIF StackOverflow PS BOZ PUIFS
FYDFQUJPO DBO BMTP CF DBVHIU
8FƊMM DPOUJOVF UIF FYQFSJNFOU CZ NBLJOH B QSPHSBN UIBU
SVOT VOUJM BO VOIBOEMFE FYDFQUJPO TUPQT UIF QBSUZ
$)"15&3  8)&/ 5)*/(4 (0 830/( 

module StoppingTheParty where

import Control.Concurrent (threadDelay)


import Control.Exception
import Control.Monad (forever)
import System.Random (randomRIO)

randomException :: IO ()
randomException = do
i <- randomRIO (1, 10 :: Int)
if i `elem` [1..9]
then throwIO DivideByZero
else throwIO StackOverflow

main :: IO ()
main = forever $ do
let tryS :: IO () -> IO (Either ArithException ())
tryS = try
_ <- tryS randomException
putStrLn "Live to loop another day!"
-- microseconds
threadDelay (1 * 1000000)

8FƊWF UBMLFE BCPVU forever CFGPSF JU DBVTFT UIF QSPHSBN


FYFDVUJPO UP MPPQ JOEFƶOJUFMZ 8F IBWF BEEFE UIF threadDelay
UP TMPX UIF MPPQJOH EPXO TP UIBU XIBUƊT IBQQFOJOH JT NPSF
$)"15&3  8)&/ 5)*/(4 (0 830/( 

OPUJDFBCMF /PUF UIBU UIF UISFBE JT EFMBZFE CZ B OVNCFS PG


NJDSPTFDPOET
5IF tryS BMMPXT JU UP TVSWJWF UIF ArithExceptionT 8F UISPX
BXBZ UIPTF FYDFQUJPOT BOE LFFQ MPPQJOH CVU XF DBO POMZ UISPX
BXBZ UIF FYDFQUJPO UIBU XF NBUDIFE PO ArithException
 "U
TPNF QPJOU XIFO PVS SBOEPN OVNCFS JT  XF XJMM UISPX BO
AsyncException JOTUFBE PG BO ArithException BOE PVS QSPHSBN
XJMM EJF B SBQJE EFBUI 5SZ NPEJGZJOH UIJT POF TP UIBU CPUI
FYDFQUJPOT BSF IBOEMFE BOE UIF MPPQ OFWFS UFSNJOBUFT

 8IZ UISPX*0


*U NBZ IBWF TFFNFE PEE UP ZPV PS OPU
UP FODPVOUFS throwIO
BCPWF 8IZ EP XF XBOU UP TUPQ B QSPHSBN CZ QVSQPTFMZ UISPX
JOH BO FYDFQUJPO *O UIF SFBM XPSME XF PǒFO EP XBOU UP EP
UIBU ƈ UP TUPQ UIF QSPHSBN XIFO TPNF DPOEJUJPO PDDVST CVU
JU NBZ CF EJƸDVMU UP TFF UIBU GSPN XIBU XFƊWF TIPXO ZPV TP
GBS
5IFSFƊT B GVODUJPO DBMMFE throw UIBU BMMPXT FYDFQUJPOT TVDI
BT UIF BSJUINFUJD FYDFQUJPOT CVU ZPV SBSFMZ VTF JU *UƊT KVTU
XIBU BMMPXT UIF div GVODUJPO UP UISPX B DivideByZero FYDFQUJPO
XIFO UIBU IBQQFOT CVU PVUTJEF PG TVDI MJCSBSZ GVODUJPOT ZPV
EPOƊU OFFE JU
5IF EJƵFSFODF CFUXFFO throw BOE throwIO DBO CF TFFO JO UIF
UZQF
$)"15&3  8)&/ 5)*/(4 (0 830/( 

throwIO :: Exception e => e -> IO a

1BSUJBMJUZ JO UIF GPSN PG UISPXJOH BO FYDFQUJPO DBO CF


UIPVHIU PG BT BO FƵFDU 5IF DPOWFOUJPOBM XBZ UP UISPX BO
FYDFQUJPO JT UP VTF throwIO XIJDI IBT IO JO JUT SFTVMU 5IJT JT
UIF TBNF UIJOH BT throw CVU throwIO FNCFET UIF FYDFQUJPO JO
IO :PV BMXBZT IBOEMF FYDFQUJPOT JO IO  )BOEMJOH FYDFQUJPOT
NVTU CF EPOF JO IO FWFO JG UIFZ XFSF UISPXO XJUIPVU BO IO UZQF
:PV BMNPTU OFWFS XBOU throw BT JU UISPXT FYDFQUJPOT XJUIPVU
BOZ XBSOJOH JO UIF UZQF FWFO IO
8FƊMM MPPL BU BO FYBNQMF PG BO VODPOEJUJPOBMMZ UISPXO FY
DFQUJPO JO IO TP ZPV DBO TFF IPX JU BƵFDUT UIF DPOUSPM ƷPX PG
ZPVS QSPHSBN

import Control.Exception

main :: IO ()
main = do
throwIO DivideByZero
putStrLn "lol"

Prelude> main
*** Exception: divide by zero

-JLF throw throwIO JT PǒFO DBMMFE GPS VT CFIJOE UIF TDFOFT


CZ MJCSBSZ GVODUJPOT 0ǒFO JO JOUFSBDUJOH XJUI UIF SFBM XPSME

8IZ #FDBVTF DBUDIJOH BOE IBOEMJOH FYDFQUJPOT NFBOT ZPV DPVME QSPEVDF EJƵFSFOU
SFTVMUT GSPN UIF TBNF JOQVUT 5IBU CSFBLT SFGFSFOUJBM USBOTQBSFODZ
$)"15&3  8)&/ 5)*/(4 (0 830/( 

XF OFFE UP UFMM PVS QSPHSBN UIBU JO DFSUBJO DPOEJUJPOT XF XBOU


JU UP TUPQ PS UP HJWF VT BO FSSPS NFTTBHF BOE MFU VT LOPX UIJOHT
XFOU XSPOH 8FƊMM UBLF B MPPL BU B DPVQMF PG FYBNQMFT GSPN
SFBM DPEF B MJCSBSZ DBMMFE IUUQDMJFOU CZ .JDIBFM 4OPZNBO
UIBU VTFT throwIO UP UISPX TPNF FYDFQUJPOT XIFO http UIJOHT
IBWFOƊU HPOF UIF XBZ XF XBOUFE UIFN UP

connectionReadLine :: Connection -> IO ByteString


connectionReadLine conn = do
bs <- connectionRead conn
when (S.null bs) $ throwIO IncompleteHeaders
connectionReadLineWith conn bs

*O UIF BCPWF throwIO XJMM UISPX BO IncompleteHeaders FYDFQ


UJPO XIFO UIF ByteString IFBEFS JT FNQUZ *O UIF OFYU FYBNQMF
JUƊT VTFE UP UISPX B ResponseTimeout FYDFQUJPO XIFO XFMM UIF
SFTQPOTF UJNFT PVU

https://www.stackage.org/package/http-client
$)"15&3  8)&/ 5)*/(4 (0 830/( 

parseStatusHeaders :: Connection
-> Maybe Int
-> Maybe (IO ())
-> IO StatusHeaders
parseStatusHeaders conn timeout' cont
| Just k <- cont = getStatusExpectContinue k
| otherwise = getStatus
where
withTimeout = case timeout' of
Nothing -> id
Just t ->
timeout t >=>
maybe (throwIO ResponseTimeout) return
-- ... other code elided ...

:PV DBO VTF IUUQDMJFOU XJUIPVU XPSSZJOH BCPVU IPX IF


NBLFT UIF FYDFQUJPOT IBQQFO #VU MFUƊT OFYU UBLF B MPPL BU
NBLJOH PVS PXO FYDFQUJPO UZQFT GPS UIPTF UJNFT XIFO ZPV EP
OFFE UP XPSSZ BCPVU JU

 .BLJOH PVS PXO FYDFQUJPO UZQFT


4PNFUJNFTƒPǒFOUJNFT XFƊMM XBOU PVS PXO FYDFQUJPO UZQFT
MJLF IUUQDMJFOU IBT 5IFZ FOBCMF VT UP CF NPSF QSFDJTF BCPVU
XIBUƊT HPJOH PO JO PVS QSPHSBN -FUƊT XPSL UISPVHI B TNBMM
$)"15&3  8)&/ 5)*/(4 (0 830/( 

FYBNQMF UP FNJU POF PG B DPVQMF EJƵFSFOU QPTTJCMF FSSPST JO


BO PUIFSXJTF TJNQMF GVODUJPO UP TFF IPX XF DPVME EP UIJT

module OurExceptions where

import Control.Exception

data NotDivThree =
NotDivThree
deriving (Eq, Show)

instance Exception NotDivThree

data NotEven =
NotEven
deriving (Eq, Show)

instance Exception NotEven

/PUF IFSF UIBU Exception JOTUBODFT BSF EFSJWBCMF ƈ ZPV EPOƊU


OFFE UP XSJUF BO JOTUBODF $POUJOVJOH PO

evenAndThreeDiv :: Int -> IO Int


evenAndThreeDiv i
| rem i 3 /= 0 = throwIO NotDivThree
| odd i = throwIO NotEven
| otherwise = return i
$)"15&3  8)&/ 5)*/(4 (0 830/( 

5IFO XFƊMM TFF UIF FSSPS BOE TVDDFTT DPOEJUJPOT

*OurExceptions> evenAndThreeDiv 0
0
*OurExceptions> evenAndThreeDiv 1
*** Exception: NotDivThree
*OurExceptions> evenAndThreeDiv 2
*** Exception: NotDivThree
*OurExceptions> evenAndThreeDiv 3
*** Exception: NotEven
*OurExceptions> evenAndThreeDiv 6
6
*OurExceptions> evenAndThreeDiv 9
*** Exception: NotEven
*OurExceptions> evenAndThreeDiv 12
12

5IFSF JT BO JTTVF XJUI UIJT TFUVQ BMUIPVHI JUƊT DPNNPO


8IBU JG XF XBOU UP LOPX XIBU JOQVU PS JOQVUT DBVTFE UIF
FSSPS 8F OFFE UP BEE DPOUFYU

"EEJOH DPOUFYU
$POWFOJFOU TVCTFDUJPO UJUMJOH "OZIPX MFUƊT NPEJGZ UIBU

module OurExceptions where

import Control.Exception
$)"15&3  8)&/ 5)*/(4 (0 830/( 

data NotDivThree =
NotDivThree Int
deriving (Eq, Show)

instance Exception NotDivThree

data NotEven =
NotEven Int
deriving (Eq, Show)

instance Exception NotEven

evenAndThreeDiv :: Int -> IO Int


evenAndThreeDiv i
| rem i 3 /= 0 = throwIO (NotDivThree i)
| odd i = throwIO (NotEven i)
| otherwise = return i

/PX XIFO XF HFU FSSPST XF DBO LOPX XIBU JOQVU DBVTFE


UIF FSSPS

*OurExceptions> evenAndThreeDiv 12
12
*OurExceptions> evenAndThreeDiv 9
*** Exception: NotEven 9
*OurExceptions> evenAndThreeDiv 8
$)"15&3  8)&/ 5)*/(4 (0 830/( 

*** Exception: NotDivThree 8


*OurExceptions> evenAndThreeDiv 3
*** Exception: NotEven 3
*OurExceptions> evenAndThreeDiv 2

$BUDI POF DBUDI BMM


/PX ZPV DBO QSPCBCMZ ƶHVSF PVU IPX UP DBUDI UIFTF UXP EJG
GFSFOU FSSPST

catchNotDivThree :: IO Int
-> (NotDivThree -> IO Int)
-> IO Int
catchNotDivThree = catch

catchNotEven :: IO Int
-> (NotDivThree -> IO Int)
-> IO Int
catchNotEven = catch

0S QFSIBQT XJUI USZ

Prelude> type EA e = IO (Either e Int)


Prelude> try (evenAndThreeDiv 2) :: EA NotEven
*** Exception: NotDivThree 2
Prelude> try (evenAndThreeDiv 2) :: EA NotDivThree
Left (NotDivThree 2)
$)"15&3  8)&/ 5)*/(4 (0 830/( 

5IF UZQF TZOPOZN JTOƊU TFNBOUJDBMMZ JNQPSUBOU CVU JU TISJOLT


UIF OPJTF B CJU /PX ZPV DPVME IBOEMF CPUI FSSPST XJUI UIF
catches GVODUJPO

catches :: IO a -> [Handler a] -> IO a

catchBoth :: IO Int
-> IO Int
catchBoth ioInt =
catches ioInt
[ Handler (\(NotEven _) -> return maxBound)
, Handler (\(NotDivThree _) -> return minBound)
]

5IF maxBoundminBound UIJOH JT OPU HPPE DPEF GPS SFBM VTF KVTU
B DPOWFOJFODF *ODJEFOUBMMZ UIF TBNF USJDL UIF SomeException
UZQF VTFT UP IJEF UZQF BSHVNFOUT JT VTFE CZ UIF Handler UZQF
UP XSBQ UIF WBMVFT JO UIF MJTU PG FYDFQUJPO IBOEMFST FYJTUFOUJBM
RVBOUJƶDBUJPO

data Handler a where


Handler :: Exception e => (e -> IO a) -> Handler a
-- Defined in ‘Control.Exception’

8F DBO NBLF B MJTU PG IBOEMFST UIBU IBOEMF FYDFQUJPOT PG


WBSZJOH UZQFT CFDBVTF UIF FYDFQUJPO UZQFT BSF FYJTUFOUJBMMZ RVBO
UJƶFE VOEFS HandlerƊT EBUBUZQF
$)"15&3  8)&/ 5)*/(4 (0 830/( 

#VU XIBU JG UIJT JTOƊU DPOWFOJFOU FOPVHI 8IBU JG XF SFBMMZ


IBWF B GBNJMZ PG TFNBOUJDBMMZ SFMBUFE PS PUIFSXJTF TJNJMBS
FYDFQUJPOT XF XBOU UP DBUDI BT B HSPVQ 'PS UIJT XF SFWJWF PVS
PME GSJFOE .Y 4VN 5ZQF

module OurExceptions where

import Control.Exception

data EATD =
NotEven Int
| NotDivThree Int
deriving (Eq, Show)

instance Exception EATD

evenAndThreeDiv :: Int -> IO Int


evenAndThreeDiv i
| rem i 3 /= 0 = throwIO (NotDivThree i)
| even i = throwIO (NotEven i)
| otherwise = return i

/PX XIFO XF XBOU UP DBUDI FJUIFS FSSPS XF POMZ OFFE POF


IBOEMFS BOE UIFO XF DBO DBTF PO UIF FYDFQUJPO UZQF KVTU MJLF
HPPE PME GBTIJPOFE EBUBUZQFT
$)"15&3  8)&/ 5)*/(4 (0 830/( 

Prelude> type EA e = IO (Either e Int)


Prelude> try (evenAndThreeDiv 0) :: EA EATD
Left (NotEven 0)
Prelude> try (evenAndThreeDiv 1) :: EA EATD
Left (NotDivThree 1)

/JǒZ FI 5IF OPUJPO IFSF JT UP FYFSDJTF UIF TBNF UBTUF


BOE KVEHNFOU JO EFTJHOJOH ZPVS FSSPS UZQFT BT ZPV XPVME JO
ZPVS IBQQZQBUI UZQFT 1SFTFSWF DPOUFYU BOE USZ UP NBLF JU TP
TPNFCPEZ DPVME VOEFSTUBOE UIF QSPCMFN ZPVƊSF TPMWJOH GSPN
UIF UZQFT *G OFDFTTBSZ 0O B EFTFSU JTMBOE 8JUI B MPU PG SVN
"OE TFB UVSUMFT

 4VSQSJTJOH JOUFSBDUJPO XJUI


CPUUPN
0OF UIJOH UP XBUDI PVU GPS JT TJUVBUJPOT XIFSF ZPV DBUDI BO
FYDFQUJPO GPS B WBMVF UIBU NJHIU CF CPUUPN %VF UP OPO
TUSJDUOFTT UIF CPUUPN DPVMEƊWF CFFO GPSDFE CFGPSF PS BǒFS
ZPVS FYDFQUJPO IBOEMFS TP ZPV NJHIU CF TVSQSJTFE JG ZPV FY
QFDUFE FJUIFS

Ƒ UIBU ZPVS FYDFQUJPO IBOEMFS XBT NFBOU UP DBUDI UIF CPU


UPN PS

Ƒ UIBU OP CPUUPNT XPVME DBVTF ZPVS QSPHSBN UP GBJM BǒFS


IBWJOH DBVHIU TBZ B SomeException
$)"15&3  8)&/ 5)*/(4 (0 830/( 

5IF QSPQFS DPQJOH NFDIBOJTN GPS UIJT JT B HMBTT PG TDPUDI


BOE UP SFBMJ[F UIF GPMMPXJOH UIJOHT

Ƒ 5IF FYDFQUJPO IBOEMJOH NFDIBOJTN JT OPU GPS OPS TIPVME


CF VTFE GPS DBUDIJOH CPUUPNT

Ƒ )BWJOH DBVHIU BO FYDFQUJPO FWFO SomeException XJUIPVU


SFUISPXJOH BO FYDFQUJPO EPFTOƊU NFBO ZPVS QSPHSBN
XPOƊU GBJM

5P EFNPOTUSBUF UIF QPJOU XFƊMM TIPX ZPV B DBTF XIFSF XF


DBVHIU BO FYDFQUJPO GSPN B CPUUPN BOE B DBTF XIFSF B CPUUPN
MFBQGSPHHFE PVS IBOEMFS

import Control.Exception

noWhammies :: IO (Either SomeException ())


noWhammies =
try undefined

megaButtums :: IO (Either SomeException ())


megaButtums =
try $ return undefined

%P ZPV UIJOL UIFTF TIPVME IBWF UIF TBNF SFTVMU 8FƊWF HPU
CBE OFXT
$)"15&3  8)&/ 5)*/(4 (0 830/( 

Prelude> noWhammies
Left Prelude.undefined
Prelude> megaButtums
Right *** Exception: Prelude.undefined

5IF JTTVF JT UIBU OPOTUSJDUOFTT NFBOT CVSZJOH UIF CPUUPN


JO B return DBVTFT UIF CPUUPN UP OPU HFU GPSDFE VOUJM ZPVƊSF
BMSFBEZ QBTU UIF try SFTVMUJOH JO BO VODBVHIU FSSPS JOTJEF UIF
Right DPOTUSVDUPS 5IF UBLFBXBZ IFSF TIPVMEOƊU CF ƌ[PNH
MB[JOFTT JT UFSSJGZJOH ƍ CVU SBUIFS ƌXSJUF UPUBM QSPHSBNT UIBU
EPOƊU VTF CPUUPNƍ *UƊT OPU KVTU VOGPSDFE CPUUPNT UIBU DBO DBVTF
QSPHSBNT UIBU TIPVMEOƊU IBWF BOZ VODBVHIU FYDFQUJPOT UP GBJM
FJUIFS UIFSFƊT BMTPƒ

 "TZODISPOPVT &YDFQUJPOT


"TZODISPOPVT FYDFQUJPOT BSF UIF QSFEBUPST IVOUJOH ZPVS IBQQZ
MJUUMF QSPHSBNT :PV QSPCBCMZ EPOƊU IBWF NVDI FYQFSJFODF
XJUI BOZUIJOH MJLF UIJT VOMFTT ZPVƊWF XSJUUFO &SMBOH CFGPSF
&WFO UIFO &SMBOHƊT BTZODISPOPVT FYDFQUJPOT BSF IBOEMFE CZ
B TFQBSBUF QSPDFTT .PTU MBOHVBHFT EPOƊU IBWF BOZUIJOH MJLF
UIJT JG POMZ CFDBVTF UIFZ EPOƊU IBWF B IPQF PG NBLJOH JU TBGF
XJUIJO UIFJS JNQMFNFOUBUJPO SVOUJNFT
$)"15&3  8)&/ 5)*/(4 (0 830/( 

module Main where

-- we haven't explained this. tough cookies.


import Control.Concurrent (forkIO, threadDelay)
import Control.Exception
import System.IO

openAndWrite :: IO ()
openAndWrite = do
h <- openFile "test.dat" WriteMode
threadDelay 1500
hPutStr h (replicate 100000000 '0' ++ "abc")
hClose h

data PleaseDie =
PleaseDie
deriving Show

instance Exception PleaseDie

main :: IO ()
main = do
threadId <- forkIO openAndWrite
threadDelay 1000
throwTo threadId PleaseDie
$)"15&3  8)&/ 5)*/(4 (0 830/( 

*G ZPV SVO UIJT QSPHSBN UIF JOUFOEFE SFTVMU JT UIBU ZPVƊMM


IBWF B ƶMF OBNFE test.dat XJUI POMZ [FSPFT UIBU EJEOƊU SFBDI
UIF ƌBCDƍ BU UIF FOE 4JODF XF DBOƊU QSFEJDU UIF GVUVSF JG ZPV
IBWF B EJTL XJUI QSFUFSOBUVSBMMZ GBTU *0 JODSFBTF UIF BSHV
NFOUT UP replicate UP SFQSPEVDF UIF JOUFOEFE JTTVF *G JU BJOƊU
CSPLFO CSFBL JU
8IBU IBQQFOFE XBT UIBU XF UISFX BO BTZODISPOPVT FYDFQ
UJPO GSPN UIF NBJO UISFBE UP PVS DIJME UISFBE TIPSUDJSDVJUJOH
XIBU XF XFSF EPJOH JO UIF NJEEMF PG EPJOH JU *G ZPV EJE UIJT
JO B MPPQ ZPVƊE MFBL ƶMF IBOEMFT UPP %POF DPOUJOVBMMZ PWFS B
QFSJPE PG UJNF MFBLJOH ƶMF IBOEMFT DBO DBVTF ZPVS QSPDFTT UP
HFU LJMMFE PS ZPVS DPNQVUFS UP CFDPNF VOTUBCMF
8F DBO UIJOL PG BTZODISPOPVT FYDFQUJPOT BT FYDFQUJPOT
SBJTFE GSPN B EJƵFSFOU UISFBE UIBO UIF POF UIBUƊMM SFDFJWF UIF
FSSPS 5IFZƊSF JNNFOTFMZ VTFGVM BOE HJWF VT B NFBOT PG UBML
JOH BCPVU FSSPS DPOEJUJPOT UIBU BSF RVJUF SFBM BOE QPTTJCMF JO
MBOHVBHFT UIBU EPOƊU IBWF GPSNBM BTZODISPOPVT FYDFQUJPOT
:PVS QSPDFTT DBO HFU BYFNVSEFSFE CZ UIF PQFSBUJOH TZTUFN
PVU PG OPXIFSF JO BOZ MBOHVBHF 8F KVTU IBQQFO UP IBWF UIF
BCJMJUZ UP EP UIF TBNF XJUIJO UIF QSPHSBNNJOH MBOHVBHF BU UIF
UISFBE MFWFM BT XFMM 5IF JTTVF JT UIBU XF XBOU UP UFNQPSBSJMZ
JHOPSF FYDFQUJPOT VOUJM XFƊWF ƶOJTIFE XIBU XFƊSF EPJOH 5IJT
JT TP UIF TUBUF PG UIF ƶMF JT DPSSFDU CVU BMTP TP UIBU XF EPOƊU MFBL
SFTPVSDFT MJLF ƶMF IBOEMFT PS QFSIBQT EBUBCBTF DPOOFDUJPOT PS
TPNFUIJOH TJNJMBS /FWFS GFBS XF DBO ƶY UIJT
$)"15&3  8)&/ 5)*/(4 (0 830/( 

module Main where

-- we haven't explained this. tough cookies.


import Control.Concurrent (forkIO, threadDelay)
import Control.Exception
import System.IO

openAndWrite :: IO ()
openAndWrite = do
h <- openFile "test.dat" AppendMode
threadDelay 1500
hPutStr h (replicate 10000000 '0' ++ "abc")
hClose h

data PleaseDie =
PleaseDie
deriving Show

instance Exception PleaseDie

main :: IO ()
main = do
threadId <- forkIO (mask_ openAndWrite)
threadDelay 1000
throwTo threadId PleaseDie
$)"15&3  8)&/ 5)*/(4 (0 830/( 

)FSF XF VTFE mask_ GSPN Control.Exception JO PSEFS UP NBTL


PS EFMBZ FYDFQUJPOT UISPXO UP PVS DIJME UISFBE VOUJM UIF IO
BDUJPO openAndWrite XBT DPNQMFUF *ODJEFOUBMMZ TJODF UIF FOE PG
UIF NBTL JT UIF MBTU UIJOH PVS DIJME UISFBE EPFT UIF FYDFQUJPO
PVS NBJO UISFBE USJFE UP UISPX UP UIF DIJME CMPXT VQ JO JUT
GBDF 8JMF & $PZPUF TUZMF BOE JT OPX UISPXO XJUIJO UIF NBJO
UISFBE

%POƊU QBOJD
"TZOD FYDFQUJPOT BSF BDUVBMMZ RVJUF IFMQGVM BOE NBOJGFTU JO
MFTT PCWJPVT XBZT JO PUIFS MBOHVBHF SVOUJNFT BOE FDPTZTUFNT
%POƊU USZ UP DBUDI FWFSZUIJOH KVTU MFU JU EJF BOE NBLF TVSF
ZPV IBWF B QSPDFTT TVQFSWJTPS BOE HPPE MPHT /P FYFDVUJPO JT
CFUUFS UIBO CBE FYFDVUJPO

 'PMMPXVQ 3FBEJOH


 " #FHJOOFSƊT (VJEF UP &YDFQUJPOT JO )BTLFMM &SJO 4XFOTPO
)FBMFZ
https://www.youtube.com/watch?v=PWS0Whf6-wc

 $IBQUFS  0WFSMBQQJOH *OQVU0VUQVU 1BSBMMFM BOE $PO


DVSSFOU 1SPHSBNNJOH JO )BTLFMM 4JNPO .BSMPX
http://chimera.labs.oreilly.com/books/1230000000929/ch08.html
$)"15&3  8)&/ 5)*/(4 (0 830/( 

 $IBQUFS  $BODFMMBUJPO BOE 5JNFPVUT 1BSBMMFM BOE $PO


DVSSFOU 1SPHSBNNJOH JO )BTLFMM 4JNPO .BSMPX
http://chimera.labs.oreilly.com/books/1230000000929/ch09.html

 "O &YUFOTJCMF %ZOBNJDBMMZ5ZQFE )JFSBSDIZ PG &YDFQ


UJPOT 4JNPO .BSMPX
http://community.haskell.org/~simonmar/papers/ext-exceptions.
pdf
$IBQUFS 

'JOBM QSPKFDU


$)"15&3  '*/"- 130+&$5 

 'JOBM QSPKFDU


'PS PVS ƶOBM QSPKFDU XFƊSF EPJOH TPNFUIJOH B MJUUMF XFJSE
CVU TNBMM BOE UIBU DBO CF NPEFSOJ[FE B CJU GSPN UIF PSJHJOBM
EFTJHO 4VSFMZ OP POF XIP LOPXT VT GSPN 5XJUUFS PS *3$ XJMM
CF TVSQSJTFE UIBU XFƊWF DIPTFO TPNFUIJOH FDDFOUSJD GPS UIJT
CVU XF GFMU JU XBT JNQPSUBOU UP TIPX ZPV BO FOEUPFOE QSPKFDU
UIBU CSJOHT JO TP NVDI SFBM XPSME JUƊMM NBLF ZPVS IFBE TQJO
*O UIJT DIBQUFS

Ƒ '*/(&3 %"&.0/4

 ƶOHFSE
%BUJOH CBDL UP  UIF ƶOHFS TFSWJDF XBT B NFBOT PG ƶHVSJOH
PVU IPX UP DPOUBDU DPMMFBHVFT PS PUIFS QFPQMF PO UIF TBNF
DPNQVUFS OFUXPSL PǒFO PO UIF TBNF NBJOGSBNF JO B UJNF
XIFO DPNQVUJOH XBT VTVBMMZ UJNFTIBSFE PO UIF TBNF QIZTJDBM
NBDIJOF #Z UIF UJNF UIF T BOE QVCMJD JOUFSOFU BDDFTT
SPMMFE JO finger XBT TPNFUJNFT VTFE UP TIBSF OPU BO PƸDF
OVNCFS BOE FNBJM BEESFTT CVU BMTP UP EFMJWFS .plan PS .project
ƶMFT BT TPSU PG QSF5XJUUFS5VNCMS NJDSPCMPH
8F VTF UIJT BT BO FYBNQMF JO QBSU CFDBVTF JUƊT OPU B UZQJDBM
XFC BQQ POMZ SFRVJSFT XPSLJOH XJUI UFYU FYQPTFT ZPV UP 5$1
TPDLFUT BOE CFDBVTF UIF UFYUCBTFE QSPUPDPM JT TQBSF BOE FBTZ

http://www.rajivshah.com/Case_Studies/Finger/Finger.htm
$)"15&3  '*/"- 130+&$5 

UP EFCVH PODF ZPV LOPX IPX 5IJT DIBQUFS JT HPJOH UP CF


TPNFXIBU NPSF 6OJY-JOVYPSJFOUFE UIBO QSFWJPVT POFT GPS
B GFX SFBTPOT 8JOEPXT VTFST XJMM ƶOE UIBU OPU BMM PG UIF
FYBNQMFT DBO CF GPMMPXFE BMPOH MJUFSBMMZ CVU UIF ƶOBM WFSTJPO
PG UIF ƶOHFS EBFNPO TIPVME XPSL

$BWFBU GPS UIF 8JOEPXT VTFST


:PV XJMM OPU CF BCMF UP GPMMPX BMM PG UIF JOTUSVDUJPOT IFSF WFS
CBUJN :PV DBO TUJMM CVJME BOE IBDL PO UIF QSPKFDU CVU JG ZPV
BSFOƊU XJMMJOH UP JOTUBMM B ƶOHFS DMJFOU GPS UFTUJOH ZPVS ƶOHFS
EBFNPO WJB $ZHXJO UIFO ZPVƊMM OFFE UP XSJUF ZPVS PXO DMJFOU

 &YQMPSJOH ƶOHFS


*G ZPV IBE fingerd SVOOJOH PO ZPVS MPDBM NBDIJOF VOEFS UIF
VTFSOBNF DBMMFO UIF SFTVMU PG IBWJOH EPOF TP NJHIU MPPL TPNF
UIJOH MJLF

$ finger callen@localhost
Login: callen Name: callen
Directory: /home/callen Shell: /bin/zsh

0O .BD 04 9 UIJT XJMM BDUVBMMZ XPSL XJUIPVU IBWJOH ƶSFE VQ


PS JOTUBMMFE B ƶOHFS TFSWJDF KVTU CZ OPU TQFDJGZJOH B IPTUOBNF
UP RVFSZ

:PV DBO TUJMM VTF finger UP DIFDL PO UIF TUBUVT PG UIF CBUISPPNT JO UIF 3BOEPN )BMM
EPSNJUPSZ BU .*5 CZ UZQJOH finger @bathroom.mit.edu JO ZPVS UFSNJOBM 5SZ JU
$)"15&3  '*/"- 130+&$5 

$ finger callen
Login: callen Name: Christopher Allen
Directory: /Users/callen Shell: /bin/bash

4QPPLZ %POƊU BTL 5IF ƶOHFS QSPUPDPM PQFSBUFT PWFS 5SBOT



NJTTJPO $POUSPM 1SPUPDPM 5$1
TPDLFUT TPNFUIJOH JU IBT
JO DPNNPO XJUI UIF QSPUPDPM VTFE CZ XFC CSPXTFST )PX
FWFS XIJMF UIFZ CPUI VTF 5$1 B ƶOHFS EBFNPO JT OPU B XFC
TFSWFS *UƊT TPNFUIJOH NVDI TJNQMFS SFBMMZ 3BUIFS UIBO IBW
JOH BO FOUJSF BQQMJDBUJPO QSPUPDPM MBZFSFE BUPQ 5$1 MJLF UIF
XFC )551
EPFT JUƊT SFBMMZ B TJOHMF NFTTBHF UFYU QSPUPDPM
3BUIFS UIBO HP JOUP B MPOH FYQMBOBUJPO PG UIF JOUFSOFU 6%1
BOE 5$1 MFUƊT TBZ 5$1 JT B QSPUPDPM GPS TFOEJOH NFTTBHFT CBDL
BOE GPSUI CFUXFFO B DMJFOU BOE B TFSWFS 5IPTF NFTTBHFT DBO
CF SBX CZUFT PS UFYU
5P TUBSU XF OFFE UP LOPX XIBU B ƶOHFS DMJFOU TFOET BOE
FYQFDUT UP SFDFJWF 'PSUVOBUFMZ UIF SFDFQUJPO TJEF JT TJNQMF "
ƶOHFS DMJFOU XJUI UIF FYDFQUJPO PG TPNF DPOUSPM DPEFT QSJOUT
UP UIF UFSNJOBM XIBUFWFS JU SFDFJWFT 4P XF KVTU OFFE UP NBLF
TVSF PVS ƶOHFS TFSWFS VOEFSTUBOET XIBU UIF DMJFOU JT TFOEJOH
5P UIBU FOE XFƊMM TUBSU PVS QSPKFDU XJUI B MJUUMF 5$1 FDIP TFSWFS
UIBU BMTP QSJOUT UIF MJUFSBM UFYU UIF DMJFOU TFOU TP UIBU XF DBO
VOEFSTUBOE UIF DBTFT XFƊSF EFBMJOH XJUI

https://en.wikipedia.org/wiki/Transmission_Control_Protocol
$)"15&3  '*/"- 130+&$5 

1SPKFDU PWFSWJFX
5P LJDL UIJT PƵ XFƊMM VTF 4UBDL XJUI UIF stack new DPNNBOE
MJLF TP

$ stack new fingerd simple

5IJT HFUT VT B TJNQMF QSPKFDU XJUI B TJOHMF FYFDVUBCMF TUBO[B


JO UIF $BCBM ƶMF 5IF ƶOBM WFSTJPO XJMM IBWF UIF GPMMPXJOH
MBZPVU

$ tree .
.
├── LICENSE
├── Setup.hs
├── fingerd.cabal
├── src
│   ├── Debug.hs
│   └── Main.hs
└── stack.yaml

ƶOHFSEDBCBM
0VS $BCBM ƶMF XJMM NFOUJPO BO FYFDVUBCMF XFƊSF OPU HPJOH UP
HJWF ZPV ZFU TP ZPV DBO MFBWF UIF QMBDFIPMEFS 4UBDL HFOFSBUFE
UIFSF GPS OPX

name: fingerd
$)"15&3  '*/"- 130+&$5 

version: 0.1.0.0
synopsis: Simple project template from stack
description: Please see README.md
homepage: https://github.com/you/fingerd
license: BSD3
license-file: LICENSE
author: Chris Allen
maintainer: [email protected]
copyright: 2016, Chris Allen
category: Web
build-type: Simple
cabal-version: >=1.10

executable debug
ghc-options: -Wall
hs-source-dirs: src
main-is: Debug.hs
default-language: Haskell2010
build-depends: base >= 4.7 && < 5
, network

executable fingerd
ghc-options: -Wall
hs-source-dirs: src
main-is: Main.hs
default-language: Haskell2010
$)"15&3  '*/"- 130+&$5 

build-depends: base >= 4.7 && < 5


, bytestring
, network
, raw-strings-qq
, sqlite-simple
, text

/PX UIBU XF IBWF UBLFO DBSF PG UIBU MFUƊT XSJUF TPNF DPEF

TSD%FCVHIT
5IJT JT PVS ƶSTU BDUVBM TPVSDF ƶMF 8FƊSF HPJOH UP VTF UIJT QSP
HSBN UP TIPX VT XIBU UIF DMJFOU TFOET BOE TFOE JU CBDL *O UIJT
SFTQFDU JUƊT BMNPTU JEFOUJDBM UP UIF FDIP TFSWFS EFNPOTUSBUFE
JO UIF EPDVNFOUBUJPO PG UIF OFUXPSL MJCSBSZ XFƊSF SFMZJOH PO
5IF EJƵFSFODF JT UIBU JU BMTP QSJOUT B MJUFSBM SFQSFTFOUBUJPO PG
UIF UFYU UIBU XBT TFOU
0VS EFCVH QSPHSBN JT B 5$1 TFSWFS TJNJMBS UP B XFC TFSWFS
XIJDI QSPWJEFT B XFC QBHF CVU MPXFS MFWFM BOE MJNJUFE UP
TFOEJOH SBX UFYU CBDL BOE GPSUI 8IBU JT EJƵFSFOU JT UIBU B XFC
TFSWFS DPNNVOJDBUFT XJUI CSPXTFST PWFS B 5$1 TPDLFU VTJOH B
TUSVDUVSFE QSPUPDPM SJDI XJUI NFUBEBUB SPVUFT BOE B TUBOEBSE
EFTDSJCJOH UIBU QSPUPDPM 8IBU XFƊSF EPJOH JT PMEFS BOE NPSF
QSJNJUJWF

https://www.stackage.org/package/network 5IF FYBNQMF XFƊSF SFGFSSJOH UP JT JO UIF Net-
work.Socket.ByteString NPEVMF $MJDL PO JU BOE MPPL GPS UIF FYBNQMF
$)"15&3  '*/"- 130+&$5 

module Main where

import Control.Monad (forever)


import Network.Socket hiding (recv)
import Network.Socket.ByteString (recv, sendAll)

logAndEcho :: Socket -> IO ()


logAndEcho sock = forever $ do
(soc, _) <- accept sock
printAndKickback soc
sClose soc
where printAndKickback conn = do
msg <- recv conn 1024
print msg
sendAll conn msg

5IJT TFUT VQ PVS TFSWFS *UT BSHVNFOU JT B TPDLFU sock


UIBU
MJTUFOT GPS OFX DMJFOU DPOOFDUJPOT EVF UP PVS VTF PG forever
UIBU TPDLFU SFNBJOT PQFO JOEFƶOJUFMZ 5IF accept BDUJPO XJMM
CMPDL VOUJM B DMJFOU DPOOFDUT UP UIF TFSWFS 5IF TPDLFU soc JT
UIF SFTVMU PG acceptJOH B DPOOFDUJPO GPS DPNNVOJDBUJOH XJUI
UIF DMJFOU
"MM XF EP XJUI UIF DMJFOU JT SFDFJWF VQ UP  CZUFT PG UFYU
GSPN UIF DMJFOU DPOOFDUJPO QSJOU UIF UFYU MJUFSBMMZ BOE UIFO
FDIP XIBU UIFZ TFOU VT CBDL UP UIF DMJFOU UIBU NBEF UIF DPO
OFDUJPO /PUF UIBU recv JT QFSNJUUFE UP SFUVSO GFXFS UIBO UIF
$)"15&3  '*/"- 130+&$5 

NBYJNVN CZUFT TQFDJƶFE JG UIBUƊT BMM UIF DMJFOU TFOU 5IFO UIF
DPOOFDUJPO UP UIF DMJFOU JT DMPTFE ƈ XF BQQMZ sClose UP soc CVU
OPU UP sock TP sock UIF TFSWFS TPDLFU SFNBJOT PQFO #FDBVTF
UIJT BDUJPO MPPQT GPSFWFS UIF OFYU UIJOH XF EP JT BXBJU BOPUIFS
DMJFOU DPOOFDUJPO

main :: IO ()
main = withSocketsDo $ do
addrinfos <- getAddrInfo
(Just (defaultHints
{addrFlags = [AI_PASSIVE]}))
Nothing (Just "79")
let serveraddr = head addrinfos
sock <- socket (addrFamily serveraddr)
Stream defaultProtocol
bindSocket sock (addrAddress serveraddr)
listen sock 1
logAndEcho sock
sClose sock

"U UIF CFHJOOJOH PG main withSocketsDo JT OPU HPJOH UP EP BOZ


UIJOH BU BMM VOMFTT ZPVƊSF PO 8JOEPXT *G ZPV BSF PO 8JOEPXT
JUƊT PCMJHBUPSZ UP VTF UIF TPDLFUT "1* JO UIF OFUXPSL MJCSBSZ 5IF
BEESFTT JOGPSNBUJPO TUVƵ JT NPTUMZ OPJTF BOE DBO CF JHOPSFE
BT B NFBOT GPS EFTDSJCJOH XIBU LJOE PG 5$1 TFSWFS XFƊSF ƶSJOH
VQ BOE XIBU QPSU JUƊT MJTUFOJOH PO
$)"15&3  '*/"- 130+&$5 

5IF JNQPSUBOU QBSU JT UIF (Just "79") QBSU ƈ UIBUƊT UIF QPSU
XFƊSF MJTUFOJOH GPS DPOOFDUJPOT PO "MTP OPUF UIBU ZPVƊMM OFFE
BENJOJTUSBUJWF QSJWJMFHFT PO NPTU PQFSBUJOH TZTUFNT UP MJTUFO
PO UIBU QPSU
0OF PG UIF JSSJUBUJPOT PG 5$1 TPDLFU MJCSBSJFT MJLF OFUXPSL
JT UIBU UIFZ DBMM FWFSZUIJOH B TPDLFU 4FSWFS MJTUFOJOH GPS DPO
OFDUJPOT 5IBUƊT B TPDLFU $MJFOU DPOOFDUJPO UIBU ZPV XFSF
MJTUFOJOH GPS 5IBUƊT B TPDLFU &WFSZUIJOHƊT B TPDLFU BOE OPUI
JOHƊT B XSFODI
"OZIPPEMF UIF OFYU CJU DPOTUSVDUT B TPSU PG TPDLFU EFTDSJQ
UPS XJUI socket 5IFO XF CJOE UIF TPDLFU UP UIF BEESFTT QPSU

XF XBOUFE -BTUMZ XF MFU UIF PQFSBUJOH TZTUFN LOPX XFƊSF QSF


QBSFE UP MJTUFO GPS DPOOFDUJPOT GSPN DMJFOUT XJUI listen 'SPN
UIFSF XF ƶSF PƵ PVS BDUVBM TFSWFS MPHJD XIJDI SVOT JOEFƶOJUFMZ
*G BOE XIFO logAndEcho ƶOJTIFT XFƊMM DMPTF UIF TPDLFU TFSWFS
BOE UIFO PVS TUPSZ JT PWFS /FYU XFƊMM ƶSF VQ UIF EFCVH TFSWFS
OPUF UIBU JUƊMM XBOU BENJOJTUSBUJWF QSJWJMFHFT GPS VTJOH QPSU 

$ sudo `stack exec which debug`


{... build noise and a password prompt ...}

5IBU XJMM HFU PVS FDIP TFSWFS TFU VQ BOE XF DBO OPX UFTU
JU VTJOH telnet UP DPOOFDU 5FMOFU JT PǒFO VTFE UP EFCVH 5$1
TFSWJDFT UIBU VTF UFYU UP DPNNVOJDBUF /PUF UIBU ZPVƊMM OFFE
UP VTF sudo PS PUIFSXJTF NBLF VTF PG BENJOJTUSBUPS QPXFST UP
TUBSU UIF QSPHSBN CFDBVTF JU XBOUT UP VTF B OFUXPSL QPSU UIBU
$)"15&3  '*/"- 130+&$5 

POMZ BENJOJTUSBUPST PS SPPU BDDPVOUT IBWF BDDFTT UP JO NPTU


PQFSBUJOH TZTUFNT 6TVBMMZ UIJT JT UIF ƶSTU  QPSUT 0ODF
ZPV IBWF UIF EFCVH TFSWFS SVOOJOH JO POF UFSNJOBM ZPVƊMM
DPOOFDU UP JU GSPN B OFX UFSNJOBM MJLF TP

$ telnet localhost 79
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.

'SPN UIFSF UFMOFU JT XBJUJOH GPS ZPV UP UZQF TPNFUIJOH BOE


UIFO IJU FOUFS

blah
blah
Connection closed by foreign host.

*O UIF BCPWF XF UZQFE ƌCMBI ƍ IJU FOUFS HPU ƌCMBIƍ FDIPFE


CBDL UP VT UIFO UIF TFSWFS DMPTFE UIF DPOOFDUJPO 3FNFNCFS
UIBU sClose JT BQQMJFE UP soc JO PVS logAndEcho GVODUJPO FOTVSJOH
UIBU UIF UFNQPSBSZ UFMOFU DPOOFDUJPO JT DMPTFE )PXFWFS UIF
TFSWFS JT TUJMM PQFO BOE ZPV DBO NBLF GVSUIFS SFRVFTUT CZ
SFPQFOJOH UIF UFMOFU DPOOFDUJPO
-FU VT UBLF B MPPL BU UIF TFSWFS UP TFF XIBU JU QSJOUFE

"blah\r\n"
$)"15&3  '*/"- 130+&$5 

8F VTFE print SBUIFS UIBO putStrLn JO logAndEcho PO QVSQPTF


TP XF DPVME HFU B MJUFSBM SFQSFTFOUBUJPO PG UIF EBUB UIBU XBT
TFOU *O UIJT DBTF UIF TUSJOH ƌCMBIƍ BOE UIF TQFDJBM DIBSBDUFST
\r BOE \n XFSF TFOU 0O 6OJYCBTFE PQFSBUJOH TZTUFNT TVDI
BT -JOVY \n JT UIF EFGBVMU MJOFFOEJOH DIBSBDUFS .JDSPTPǒ
8JOEPXT VTFT \r GPMMPXFE CZ \n GPS UIF TBNF
)BWJOH EPOF UIBU MFU VT OPX EP UIF TBNF XJUI BO BDUVBM
ƶOHFS DMJFOU

$ finger callen@localhost
[localhost]
Trying 127.0.0.1...
callen
$ finger @localhost
[localhost]
Trying 127.0.0.1...

1BSUJDVMBSMZ JG ZPVƊSF PO B .BD ZPV NBZ HFU TPNF OPJTF


IFSF MJLF UIJT

Trying ::1...
finger: connect: Connection refused
Trying 127.0.0.1...

*U TIPVME DPOOFDU BǒFS UIBU *U BUUFNQUT UP VTF *1W ƶSTU UP


SFBDI ZPVS ƶOHFS EBFNPO XIFO JU DBOƊU JU TIPVME VTF *1W
:PV DBO QSPCBCMZ JHOPSF UIJT
$)"15&3  '*/"- 130+&$5 

5IFO UIF PVUQVU TFSWFSTJEF GPS UIJT XPVME CF

"callen\r\n"
"\r\n"

5IF ƶSTU DPNNBOE BTLFE UIF ƶOHFS EBFNPO SVOOJOH BU


MPDBMIPTU GPS JOGPSNBUJPO PO UIF VTFS DBMMFO UIF TFDPOE BTLFE
GPS B MJTUJOH PG VTFST 8JUI UIF QSJOUFE PVUQVU UIF TFSWFS HBWF
VT XF OPX LOPX XIBU RVFSJFT GSPN BO BDUVBM ƶOHFS DMJFOU XJMM
MPPL MJLF UP PVS 5$1 TFSWFS 8JUI UIBU EPOF XFƊMM OPX XSJUF
VQ UIF ƶOBM 5$1 TFSWFS JUTFMG

 4MJHIUMZ NPEFSOJ[FE ƶOHFSE


)JTUPSJDBMMZ UIF EBUB UIBU finger SFUVSOT BCPVU VTFST XBT QBSU PG
UIF PQFSBUJOH TZTUFN 5IBU JOGPSNBUJPO JT TUJMM UZQJDBMMZ TUPSFE
JO UIF 04 CVU GPS TFDVSJUZ SFBTPOT JUƊT OP MPOHFS SPVUJOFMZ
TIBSFE UISPVHI ƶOHFS SFRVFTUT 8FƊSF HPJOH UP VQEBUF UIF
TPVSDF PG EBUB GPS finger CZ VTJOH BO FNCFEEFE 42- EBUBCBTF
DBMMFE 42-JUF " EBUBCBTF JT B DPOWFOJFOU ZFU SPCVTU XBZ PG
TPSUJOH BOE SFBEJOH EBUB BOE 42-JUF JT B MJHIUXFJHIU EBUBCBTF
5IF EBUB XJMM CF TUPSFE JO B ƶMF XJUIJO UIF NBJO QSPKFDU EJSFD
UPSZ TP UIFSF XPOƊU CF B MPU PG NZTUFSZ PS NBHJD JOWPMWFE JO
JOUFSBDUJOH XJUI JU

1SPOPVODFE ƌTRVJSSFMƍ
$)"15&3  '*/"- 130+&$5 

'JSTU XFƊMM TIPX ZPV UIF 5$1 TFSWFSƊT GSBNJOH PG UIF MPHJD
UIFO XFƊMM TIPX ZPV IPX UIF EBUBCBTF JOUFSBDUJPO XPSLT 'SPN
IFSF BMM UIF DPEF HPFT JOUP ZPVS Main.hs ƶMF

{-# LANGUAGE OverloadedStrings #-}


{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}

OverloadedStrings ZPV BMSFBEZ LOPX QuasiQuotes JT GPS UIF


MJUFSBMT XIJDI ZPVƊWF TFFO CFGPSF RecordWildCards JT UIF OFX
POF BOE JTOƊU UPP EJƸDVMU UP ƶHVSF PVU *U TQBSFT VT NBOVBMMZ
ZBOLJOH UIF DPOUFOUT PG B SFDPSE JOUP TDPQF JOTUFBE UIF SFDPSE
BDDFTTPST CFDPNF CJOEJOHT UP UIF DPOUFOUT TVDI UIBU

{-# LANGUAGE RecordWildCards #-}

module RWCDemo where

data Blah =
Blah { myThing :: Int }

wew Blah{..} = print myThing

wew XJMM QSJOU UIF myThing JOTJEF PG UIF Blah BSHVNFOU JU JT


BQQMJFE UP XJUIPVU OFFEJOH UP BQQMZ myThing UP B Blah WBMVF PS
UP EFTUSVDUVSF UIF DPOUFOUT PG Blah JO UIF QBUUFSO NBUDI *UƊT
QVSFMZ B DPOWFOJFODF
$)"15&3  '*/"- 130+&$5 

module Main where

import Control.Exception
import Control.Monad (forever)
import Data.List (intersperse)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (decodeUtf8, encodeUtf8)

8FƊMM OFFE UIF BCJMJUZ UP EFDPEF B Text WBMVF GSPN B 65'


#ZUF4USJOH BOE UIFO SFFODPEF B Text WBMVF BT B 65' #ZUF4USJOH

import Data.Typeable
import Database.SQLite.Simple hiding (close)
import qualified Database.SQLite.Simple as SQLite
import Database.SQLite.Simple.Types
import Network.Socket hiding (close, recv)
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Network.Socket.ByteString (recv, sendAll)
import Text.RawString.QQ

$SFBUJOH UIF EBUBCBTF 8FƊSF VTJOH UIF TRMJUFTJNQMF MJCSBSZ UP


NBLF B TFMGDPOUBJOFE EBUBCBTF TUPSFE JO B ƶMF JO UIF TBNF
EJSFDUPSZ BT PVS QSPKFDU 5IJT XJMM BDU BT UIF SFQPTJUPSZ PG VTFST
PVS ƶOHFS EBFNPO DBO SFQPSU PO
$)"15&3  '*/"- 130+&$5 

data User =
User {
userId :: Integer
, username :: Text
, shell :: Text
, homeDirectory :: Text
, realName :: Text
, phone :: Text
} deriving (Eq, Show)

/PX XF EJH JOUP XIFSF UIF EBUB DPNFT GSPN User JT UIF
EBUBUZQF EFTDSJCJOH PVS VTFS SFDPSET *UƊT OPU TVQFS TUSVDUVSFE
PS JOUFSFTUJOH CVU HFUT UIJOHT SPMMJOH 5IF POMZ CJU QPUFOUJBMMZ
PVU PG UIF PSEJOBSZ IFSF JT UIBU XF IBWF B userId ƶFME PG UZQF
Integer JO PSEFS UP QSPWJEF UIF EBUBCBTF XIBUƊT DBMMFE B QSJNBSZ
LFZ  5IJT JT UP QSPWJEF B NFBOT PG VOJRVFMZ JEFOUJGZJOH EBUB
JO UIF EBUBCBTF JOEFQFOEFOU PG UIF UFYU ƶFMET JO PVS SFDPSE
UZQF BNPOH PUIFS UIJOHT

https://en.wikipedia.org/wiki/Unique_key
$)"15&3  '*/"- 130+&$5 

instance FromRow User where


fromRow = User <$> field
<*> field
<*> field
<*> field
<*> field
<*> field

instance ToRow User where


toRow (User id_ username shell homeDir
realName phone) =
toRow (id_, username, shell, homeDir,
realName, phone)

#PJMFSQMBUF GPS NBSTIBMMJOH BOE VONBSTIBMMJOH EBUB UP BOE


GSPN UIF 42-JUF EBUBCBTF 5IJT TIPVME SFNJOE ZPV PG FromJSON
BOE ToJSON

createUsers :: Query
createUsers = [r|
CREATE TABLE IF NOT EXISTS users
(id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE,
shell TEXT, homeDirectory TEXT,
realName TEXT, phone TEXT)
|]
$)"15&3  '*/"- 130+&$5 

5IF Query UZQF JT KVTU B OFXUZQF XSBQQFS GPS B Text WBMVF


$POWFOJFOUMZ Query IBT BO IsString JOTUBODF TP TUSJOH MJUFSBMT
DBO CF Query WBMVFT 5IJT JTOƊU SFBMMZ B RVFSZ UIPVHI JUƊT BD
UVBMMZ B 42- TUBUFNFOU EFƶOJOH UIF EBUBCBTF UBCMF UIBU XJMM
DPOUBJO PVS VTFS EBUB 5IF QSJNBSZ LFZ TUVƵ JT OPJTF TBZJOH
UIBU UIF SPX JT OBNFE ƌJEƍ BOE UIBU XF XBOU UIBU ƶFME UP BVUP
JODSFNFOU XJUIPVU OFFEJOH UP EP JU PVSTFMWFT 5IBU JT JG UIF
MBTU SPX XF JOTFSUFE JOUP UIF EBUBCBTF IBE JE ƌƍ UIFO UIF OFX
POF XJMM CF BVUPBTTJHOFE UIF QSJNBSZ LFZ ƌƍ 5IF SFTU PG JU
JT TUSBJHIUGPSXBSE EFTDSJCJOH ƶFME OBNFT BOE UIFJS SFQSFTFO
UBUJPO ƌ5&95ƍ
CVU ZPVƊMM OPUF XF SFRVJSF VTFSOBNFT UP CF
VOJRVF TP UIBU UIFSF DBOOPU CF UXP User WBMVFT XJUI UIF TBNF
VTFSOBNF

insertUser :: Query
insertUser =
"INSERT INTO users VALUES (?, ?, ?, ?, ?, ?)"

allUsers :: Query
allUsers =
"SELECT * from users"

getUserQuery :: Query
getUserQuery =
"SELECT * from users where username = ?"
$)"15&3  '*/"- 130+&$5 

5IJT JT VUJMJUZ TUVƵ GPS JOTFSUJOH B OFX VTFS HFUUJOH BMM VTFST
GSPN UIF VTFS UBCMF BOE HFUUJOH BMM UIF ƶFMET GPS B TJOHMF VTFS
XJUI B QBSUJDVMBS VTFSOBNF 5IF RVFTUJPO NBSLT BSF IPX UIF
TRMJUFTJNQMF MJCSBSZ QBSBNFUFSJ[FT EBUBCBTF RVFSJFT

data DuplicateData =
DuplicateData
deriving (Eq, Show, Typeable)

instance Exception DuplicateData

5IF UZQF BCPWF JT B POFPƵ FYDFQUJPO XF UISPX XIFOFWFS


XF HFU TPNFUIJOH PUIFS UIBO [FSP PS POF VTFST GPS B QBSUJDVMBS
VTFSOBNF 5IBU TIPVME CF JNQPTTJCMF CVU ZPV OFWFS LOPX

type UserRow =
(Null, Text, Text, Text, Text, Text)

UserRow JT B UZQF TZOPOZN GPS UIF UVQMFT XF JOTFSU UP DSFBUF


B OFX VTFS

getUser :: Connection -> Text -> IO (Maybe User)


getUser conn username = do
results <- query conn getUserQuery (Only username)
case results of
[] -> return $ Nothing
[user] -> return $ Just user
_ -> throwIO DuplicateData
$)"15&3  '*/"- 130+&$5 

5IF Only EBUB DPOTUSVDUPS JT IPX XF QBTT B TJOHMF BSHVNFOU


JOTUFBE PG B PSHSFBUFS UVQMF UP PVS RVFSZ QBSBNFUFST XIFO
VTJOH UIF TRMJUFTJNQMF MJCSBSZ 5IJT JT OFFEFE CFDBVTF CBTF IBT
OP POFUVQMF UZQF BOE getUserQuery UBLFT B TJOHMF QBSBNFUFS
8F DIFDL GPS OPOF POF PS NBOZ SFTVMUT DPOWFSUJOH JU JOUP B
Nothing Just PS IO FYDFQUJPO

createDatabase :: IO ()
createDatabase = do
conn <- open "finger.db"
execute_ conn createUsers
execute conn insertUser meRow
rows <- query_ conn allUsers
mapM_ print (rows :: [User])
SQLite.close conn
where meRow :: UserRow
meRow = (Null, "callen", "/bin/zsh",
"/home/callen", "Chris Allen",
"555-123-4567")

'JOBMMZ XF IBWF B VUJMJUZ GVODUJPO GPS DSFBUJOH UIF EBUBCBTF


XJUI B TJOHMF FYBNQMF SPX PG EBUB 3VOOJOH UIJT B TFDPOE UJNF
XJMM FSSPS XJUIPVU DIBOHJOH UIF EBUBCBTF *G ZPV OFFE PS XBOU
UP SFTFU UIF EBUBCBTF ZPV DBO EFMFUF UIF finger.db ƶMF
$)"15&3  '*/"- 130+&$5 

#FGPSF ZPV DPOUJOVF 5IF DPEF UIBU GPMMPXT XJMM BTTVNF BOE
SFRVJSF B TRMJUF EBUBCBTF CZ UIF OBNF PG finger.db XJUI UIF
TDIFNB PVUMJOFE JO createUsers FYJTUT JO UIF TBNF EJSFDUPSZ
BT XIFSF ZPV SVO ZPVS fingerd TFSWJDF 5P SVO createDatabase
ZPV DPVME EP UIF GPMMPXJOH

$ stack ghci --main-is fingerd:exe:fingerd


{... noise noise ...}
Prelude> createDatabase
User {userId = 1, ... noise ... }

8JUI UIBU JO QMBDF ZPV DBO DPOUJOVF JNQMFNFOUJOH ZPVS


ƶOHFS EBFNPO

-FU ZPVS ƶOHFST EP UIF XBMLJOH


8FƊSF TUJMM JO PVS Main NPEVMF IFSF :PV TIPVME IBWF DSFBUFE
UIF EBUBCBTF BMSFBEZ CVU OPX XFƊMM XSJUF UIF GVODUJPOT UIBU
XJMM BMMPX UIF TFSWFS UP MJTUFO BOE SFTQPOE UP DMJFOU RVFSJFT

returnUsers :: Connection -> Socket -> IO ()


returnUsers dbConn soc = do
rows <- query_ dbConn allUsers
let usernames = map username rows
newlineSeparated =
T.concat $ intersperse "\n" usernames
sendAll soc (encodeUtf8 newlineSeparated)
$)"15&3  '*/"- 130+&$5 

returnUsers VTFT B EBUBCBTF Connection BOE B Socket GPS UBML


JOH UP UIF VTFS 5IF EBUBCBTF DPOOFDUJPO JT VTFE UP HFU B MJTU PG
BMM UIF VTFST JO UIF EBUBCBTF XIJDI JT UIFO DIBOHFE JOUP B OFX
MJOF TFQBSBUFE Text WBMVF 5IFO UIBU JT FODPEFE JOUP B 65'
#ZUF4USJOH XIJDI JT TFOU UISPVHI UIF TPDLFU UP UIF DMJFOU

formatUser :: User -> ByteString


formatUser (User _ username shell
homeDir realName _) = BS.concat
["Login: ", e username, "\t\t\t\t",
"Name: ", e realName, "\n",
"Directory: ", e homeDir, "\t\t\t",
"Shell: ", e shell, "\n"]
where e = encodeUtf8

5IJT GVODUJPO JT VTFE UP GPSNBU User SFDPSET BT B 65'


#ZUF4USJOH WBMVF 5IF GPSNBU JT JOUFOEFE UP NJNJD QPQVMBS
fingerd JNQMFNFOUBUJPOT CVU XFƊSF OPU HPJOH GPS QSFDJTJPO
IFSF
$)"15&3  '*/"- 130+&$5 

returnUser :: Connection -> Socket -> Text -> IO ()


returnUser dbConn soc username = do
maybeUser <- getUser dbConn (T.strip username)
case maybeUser of
Nothing -> do
putStrLn
("Couldn't find matching user for username: "
++ (show username))
return ()
Just user -> sendAll soc (formatUser user)

5IJT JT UIF TJOHMF VTFS RVFSZ DBTF XIFSF XF VTF formatUser


UP QSPWJEF EFUBJMFE JOGPSNBUJPO UP UIF DMJFOU PO B TJOHMF VTFS
8F IBWF UP IBOEMF UIF DBTF XIFSF OP VTFS CZ UIF VTFSOBNF
QSPWJEFE XBT GPVOE "T JU TUBOET UIF Nothing DBTF IFSF XJMM
QSJOU UIF SFQPSU UIBU OP VTFS XBT GPVOE CZ UIBU VTFSOBNF JO UIF
TFSWFS UFSNJOBM CVU XJMM OPU TFOE UIBU JOGPSNBUJPO ƈ PS BOZ
JOGPSNBUJPO ƈ UP UIF DMJFOU TJEF :PV NBZ XBOU UP DIBOHF UIBU
BT JU NJHIU CF VTFGVM UP UFMM UIF FOE VTFS XIZ OP JOGPSNBUJPO
XBT SFUVSOFE
*G B VTFS JT GPVOE XF TFOE UIF GPSNBUUFE #ZUF4USJOH PG UIF
User SFDPSE UP UIF DMJFOU 5IF TUSJQQJOH PG UIF VTFSOBNF UFYU
QSJPS UP RVFSZJOH JT CFDBVTF UIF MJUFSBM EBUB TFOU GPS B VTFS
OBNF RVFSZ JT "yourname\r\n" BOE JO PSEFS GPS UIBU UP NBUDI
ƌZPVSOBNF ƍ XF OFFE UP TUSJQ UIF DPOUSPM DIBSBDUFST GSPN UIF
UFYU XIJDI strip GSPN Data.Text EPFT GPS VT
$)"15&3  '*/"- 130+&$5 

handleQuery :: Connection -> Socket -> IO ()


handleQuery dbConn soc = do
msg <- recv soc 1024
case msg of
"\r\n" -> returnUsers dbConn soc
name -> returnUser dbConn soc (decodeUtf8 name)

handleQuery SFDFJWFT VQ UP  CZUFT PG EBUB #BTFE PO


UIBU EBUB UIF DMJFOU TFOET UP UIF TFSWFS UIF DBTF EJTDSJNJOBUFT
CFUXFFO XIFO JU TIPVME TFOE B MJTU PG BMM VTFST PS POMZ B TJOHMF
VTFS 'PSUVOBUFMZ UIF QSPUPDPM JT SFMBUJWFMZ VODPNQMJDBUFE TP
XF EPOƊU FWFO IBWF UP EP BOZ QBSTJOH BT XPVME PSEJOBSJMZ CF
SFRVJSFE GPS DPNNVOJDBUJOH XJUI B NPSF FMBCPSBUF QSPUPDPM

handleQueries :: Connection -> Socket -> IO ()


handleQueries dbConn sock = forever $ do
(soc, _) <- accept sock
putStrLn "Got connection, handling query"
handleQuery dbConn soc
sClose soc

*UƊT TJNJMBS UP UIF FDIP TFSWFS TBWF GPS UIF BEEJUJPOBM BS
HVNFOU PG UIF EBUBCBTF DPOOFDUJPO BOE UIF MPHHJOH PG XIFO
DPOOFDUJPOT XFSF BDDFQUFE
$)"15&3  '*/"- 130+&$5 

main :: IO ()
main = withSocketsDo $ do
addrinfos <-
getAddrInfo
(Just (defaultHints {addrFlags = [AI_PASSIVE]}))
Nothing (Just "79")
let serveraddr = head addrinfos
sock <- socket (addrFamily serveraddr)
Stream defaultProtocol
bindSocket sock (addrAddress serveraddr)
listen sock 1
-- only one connection open at a time
conn <- open "finger.db"
handleQueries conn sock
SQLite.close conn
sClose sock

5IF POMZ OFX CJU BCPWF JT UIF PQFOJOH PG B DPOOFDUJPO UP B


42-JUF EBUBCBTF MPDBUFE JO UIF TBNF EJSFDUPSZ BT ZPVS QSPKFDU
5IF DPOOFDUJPO UP UIF EBUBCBTF JT QBTTFE UP UIF RVFSZIBOEMJOH
DPEF XIJDI SVOT JOEFƶOJUFMZ MJLF UIF FDIPBOEMPH TFSWFS *G
JU TPNFIPX TUPQT XJUIPVU UISPXJOH BO FYDFQUJPO XF DMPTF UIF
TFSWFS TPDLFU KVTU UP CF HPPE MJUUMF QSPHSBNNFST
/PX XFƊSF EPOF BTTVNJOH ZPVƊWF DSFBUFE B 42-JUF EBUBCBTF
VTJOH createDatabase XIJDI JT WBMJE BOE BDDFTTJCMF UP ZPVS QSP
$)"15&3  '*/"- 130+&$5 

HSBN UIF GPMMPXJOH TIPVME XPSL :PVƊMM XBOU UP EP UIJT JO POF


UFSNJOBM

$ stack build
$ sudo `stack exec which fingerd`

5IFO JO BOPUIFS EJƵFSFOU TIFMM TFTTJPO UIF GPMMPXJOH TIPVME


XPSL

$ finger callen@localhost
Login: callen Name: Chris Allen
Directory: /home/callen Shell: /bin/zsh

"OE UIBUƊT JU *O UIF FYFSDJTFT XFƊWF HJWFO TPNF XBZT UP


FYUFOE UIJT BOE XF IPQF ZPVƊWF FOKPZFE UIJT MJUUMF GPSBZ JOUP
5$1 TPDLFUT BOE CBTJD OFUXPSLJOH 4FDVSJUZ DPODFSOT BTJEF
UIF ƶOHFS QSPUPDPM IBT CFFO VTFE PWFS UIF ZFBST GPS TPNF
QSFUUZ DPPM UIJOHT 1FSIBQT NPTU GBNPVTMZ +PIO $BSNBDL
VTFE .plan ƶMFT BT B LJOE PG NJDSPCMPH UP EFMJWFS VQEBUFT PO
UIF EFWFMPQNFOU QSPDFTT PG 2VBLF

 $IBQUFS &YFSDJTFT


 5SZ VTJOH UIF sqlite3 DPNNBOE MJOF JOUFSGBDF UP BEE B
OFX VTFS PS NPEJGZ BO FYJTUJOH VTFS JO finger.db

http://atrophied.co.uk/read/john-carmacks-plan-archive
$)"15&3  '*/"- 130+&$5 

 8SJUF BO FYFDVUBCMF TFQBSBUF PG fingerd BOE debug XIJDI


BMMPXT ZPV UP BEE OFX VTFST UP UIF EBUBCBTF

 "EE UIF BCJMJUZ UP NPEJGZ BO FYJTUJOH VTFS JO UIF EBUBCBTF

 #PVOE PO B EJƵFSFOU QPSU USZ DSFBUJOH B ƌDPOUSPM TPDLFUƍ


UIBU QFSNJUT JOTFSUJOH OFX EBUB JOUP UIF EBUBCBTF XIJMF
UIF TFSWFS JT SVOOJOH 5IJT XJMM QSPCBCMZ SFRVJSF BU NJOJ
NVN MFBSOJOH IPX UP VTF forkIO BOE UIF CBTJDT PG DPODVS
SFODZ JO )BTLFMM BNPOH PUIFS UIJOHT %FTJHO UIF GPSNBU
GPS SFQSFTFOUJOH UIF VTFS SPXT QBTTFE PWFS UIF 5$1 TPDLFU
ZPVSTFMG 'PS CPOVT QPJOUT XSJUF ZPVS PXO DMJFOU FYF
DVUBCMF UIBU UBLFT UIF BSHVNFOUT GSPN UIF DPNNBOE MJOF
BT XFMM

 $FMFCSBUF DPNQMFUJOH UIJT NBTTJWF CPPL


*OEFY


 BOPOZNPVT GVODUJPO  

BOPOZNPVT QSPEVDU 
VOJU  BOPOZNPVT TZOUBY 

 BQQMJDBUJPO    

 BSCJUSBSZ QSFDJTJPO 
  BSHVNFOU     
CSPXTF    
JOGP  BSHVNFOU
  NVMUJQMF 
  Ƈ BSJUINFUJD 
BSJUZ  
BCT  BTTPDJBUJWJUZ   
BCTUSBDUJPO  
BCTUSBDUJPO CBDLUSBDLJOH  
MBNCEB  CBTF 
BMHFCSB   CBTF DBTF   
BMQIB FRVJWBMFODF   CFUB SFEVDUJPO Ƈ  
BNCJHVPVT UZQF  CJOBSZ USFF 
BOBSDIZ  CJOEJOH  
BOPOZNPVT  CJOEJOH

$)"15&3  '*/"- 130+&$5 

MPDBM  DPMVNO 


#PPM      DPNCJOBUPS  
   DPNNVUBUJWF 
CPPM  DPNQBSF 
#PPMF $PNQPTF UZQF 
(FPSHF  DPNQPTJUJPO Ƈ 
CPPMFBO     
#PPMFBO DPODBU 
MPHJD  DPODBUFOBUJPO  
CPUUPN     DPODSFUF UZQF   
#PVOEFE   
DPODSFUF UZQFT 
$"'  DPOEJUJPOBM 
DBSEJOBMJUZ   DPOKVODUJPO 
$BSOBQ DPOT 
3VEPMG  DPOT DFMM 
DBTF  DPOTUBOU BQQMJDBUJWF GPSN
DBTF FYQSFTTJPO Ƈ 
 DPOTUSBJOFE QPMZNPSQIJTN
$IBS    
DIBSBDUFS  DPOTUSVDUPS   
DIBSBDUFS DPOTUSVDUPS
BMQIBCFUJDBM  EBUB  
VOJDPEF  UZQF Ƈ
DIBSBDUFST  DVSSZ 
$IVSDI "MPO[P  $VSSZ )BTLFMM 
$)"15&3  '*/"- 130+&$5 

DVSSZJOH    EJWJTJPO




EBUB 
GSBDUJPOBM 
EBUB DPOTUSVDUPS  
EP 
    
%PVCMF 
Ƈ 
ESPQ 
EBUB EFDMBSBUJPO 
ESPQ8IJMF 
EBUB TUSVDUVSF 
%BUB#PPM  &OVN    
EBUBUZQF     
     FOVN'SPN5P 
EBUBUZQF &R    
BMHFCSBJD  Ƈ   
EFDMBSBUJPO     
    FRVBMJUZ   
EFDMBSBUJPO FSSPS
EBUB Ƈ $PVME OPU EFEVDF 
EFOPUBUJPO   
EFOPUFT  FYQFDUFE UZQF  
EFSJWJOH     FYQFDUFE WFSTVT BDUVBM
 UZQF 
EFSJWJOH DMBVTF  FYQFDUFE WT BDUVBM UZQF
EFSJWJOH 4IPX     
EJTKVODUJPO     /P JOTUBODF GPS  
EJTQMBZ      
EJWJTJPO      
$)"15&3  '*/"- 130+&$5 

OP JOTUBODF GPS  ƶCPOBDDJ   


/PU JO TDPQF  ƶMF    
FWBMVBUF  ƷBHT
FWBMVBUJPO    8BMM 
FWBMVBUJPO 'MPBU 
JOTJEF PVU  GNBQ 
PVUTJEF JO  'SBDUJPOBM 
SFDVSTJWF GVODUJPO  GSBDUJPOBM  
 GSPN*OUFHSBM 
FYDFQUJPO  Ƈ GVODUJPO      
&YDFQUJPO   
OP QBSTF  GVODUJPO ƶSTUDMBTT
/POFYIBVTUJWF QBUUFSOT BOPOZNPVT 
 BQQMJDBUJPO   
FYDFQUJPO BSHVNFOUT 
.JTTJOH ƶFME  DBMM 
/P NBUDI  NBUIFNBUJDBM 
/POFYIBVTUJWF QBUUFSOT PQFSBUPS 
 QSFƶY 
FYQPOFOUJBUJPO  TUSVDUVSF  
FYQSFTTJPO       GVODUJPO BQQMJDBUJPO 
     
&YUFOTJPOT GVODUJPO UZQF  

/P*NQMJDJU1SFMVEF  GVODUJPOT


ƶSTUDMBTT 
GBDUPSJBM  'VODUPS  
$)"15&3  '*/"- 130+&$5 

GVTJPO  JEFOUJUZ WBMVF 


JGUIFOFMTF Ƈ
()$J     
Ƈ 
()$J
JGUIFOFMTF
JOGP   
FYQSFTTJPO 
MPBE 
JNQPSU   
NPEVMF 
JO 
UZQF 
JOEFOUBUJPO  
CMPDL TZOUBY  
JOƶY     
DPNNBOET 
JOƶY
XBSOJOH 
BTTPDJBUJWJUZ 
HP TZOUBY 
JOƶYM 
HVBSE     
JOƶYS 
HVBSEFE SFDVSTJPO 
QBSFOUIFTJ[BUJPO GPS
)BDLBHF 
QSFƶY VTF 
)BTLFMM OJOKBT 
QSFDFEFODF 
)BTLFMM 3FQPSU 
JOƶY PQFSBUPS 
IJHIFSLJOEFE UZQF 
JOIBCJU 

JOQVU 
IJHIFSPSEFS GVODUJPO 
JOQVUPVUQVU 
 
JOTJEF PVU 
IJHIFSPSEFS GVODUJPOT 
JOTUBODF 
)PPHMF 
*OU Ƈ
JEFOUJUZ  *OUFHFS   
*EFOUJUZ UZQF
 *OUFHSBM 
JEFOUJUZ GVODUJPO    JOUFHSBM  
$)"15&3  '*/"- 130+&$5 

JOUFSGBDF  MJTU      


JOWPDBUJPO  MJUFSBM 
*0  Ƈ MPDBM 
*0
NBJO   
BDUJPO 
NBJO  *0

*0

NBQ 
*0 BDUJPO 
NBUI 
LJOE  NBY 
LJOET  .BZCF    
NFNPSZ 
MBNCEB  
NJO 
MBNCEB DBMDVMVT   
NPEVMF    
 

MBNCEB UFSN 
.POPJE 
MBX 
NPOPNPSQIJTN SFTUSJDUJPO
MBX BCJEJOH 

MBX CSFBLJOH 
MFOHUI   OFHBUJPO 
MFU       OFTUJOH  
 OFXMJOF 
MFU OFXUZQF  
FYQSFTTJPO  OJM 
TUBUFNFOU  OPOFYIBVTUJWF QBUUFSOT
MJOF    
MJOFBS  /PO&NQUZ 
-JTQ  OPOFYIBVTUJWF QBUUFSOT 
$)"15&3  '*/"- 130+&$5 

OPOTUSJDU   PWFSƷPX 


OPOTUSJDU FWBMVBUJPO  PWFSMPBEFE TUSJOHT 
OPSNBM GPSN    
OPSNBM PSEFS    QBSBNFUFS  

OVMMBSZ  QBSBNFUSJD QPMZNPSQIJTN


 
OVMMBSZ EBUB DPOTUSVDUPS 
OVMMBSZ UZQF  QBSBNFUSJDJUZ   

/VN      QBSFOUIFTFT    

   

OVNCFS     QBSUJBM BQQMJDBUJPO  



OVNCFS
QBSUJBM GVODUJPO  
MJUFSBM 
    
XIPMF 

OVNFSJD MJUFSBM 
QBUUFSO NBUDI   
OVNFSJDBM MJUFSBM 
QBUUFSO NBUDI
PQFSBUPS    OPOFYIBVTUJWF 
PQFSBUPS QBUUFSO NBUDIJOH  
GVODUJPO  Ƈ  Ƈ
0SE        
     QFOHVJOT 
  QJQF 
0SEFSJOH  QPJOUGSFF Ƈ  
PSQIBO JOTUBODF  QPMZNPSQIJD MJUFSBMT 
PUIFSXJTF   QPMZNPSQIJTN   
PVUTJEF JO      
$)"15&3  '*/"- 130+&$5 

 QVU4US-O  


QPMZNPSQIJTN
2VJDL$IFDL 
BE IPD    
   SBOHF 
DPOTUSBJOFE    3BUJPOBM 
    3FBE   
QBSBNFUSJD  3FBE
QSFDFEFODF   JT OPU HPPE  
QSFƶY   3FBM 
1SFMVEF   SFDPSE
QSJOU      BDDFTTPS 
Ƈ    SFDVSTJPO 
QSJOU JU  SFDVSTJWF
QSJOUJOH  UZQF 
QSPEVDU    SFDVSTJWF GVODUJPO  
QSPEVDU UZQF     
QSPƶMJOH SFEFY  
IFBQ  SFEFY
UJNF  SFEVDJCMF FYQSFTTJPOT 
QSPHSBNNJOH MBOHVBHF  SFEVDF 
QSPNQU  SFEVDUJPO    
QSPQFSUZ UFTUJOH  SFGFSFOUJBM USBOTQBSFODZ 
QVSF GVODUJPOBM SFNBJOEFS 
QSPHSBNNJOH  3&1-    
QVSJUZ   3&1-
QVU4US  3FBEFWBMQSJOU MPPQ 
$)"15&3  '*/"- 130+&$5 

SVOUJNF FYDFQUJPO  4USJOH     


    
TDBO 
   
4DI¶OƶOLFM .PTFT 
TUSJOH 
4DJFOUJƶD 
TUSJOHT  
TDPQF     
TUZMF 
  
TVCDMBTT 
TDPQF
TVHBS 
MFYJDBM  
TVN UZQF    
TFDUJPOJOH  
   
TFSJBMJ[BUJPO  
TVN UZQF
TFTTJPO 

TFU 
QJQF 
TFU
TVQFSDMBTT  
UIFPSZ 
TZOUBDUJD TVHBS 
TIBEPXJOH Ƈ
TZOUBY 
4IPX     
   Ƈ UBLF 
 UBLF8IJMF 
TJEF FƵFDU  UFSN  
TJEF FƵFDUT   UFSNMFWFM 
TPVSDF DPEF  UFSNJOBUF  
TPVSDF DPEF UFSNT 
ƶMF  UFYU  
TQJOF   UIVOL 
TQMJU"U  UPQMFWFM   
$)"15&3  '*/"- 130+&$5 

UPUBM GVODUJPO  DPOTUSBJOU  


5SJWJBM   EJTQBUDIFE CZ UZQF 
UVQMF       
 UZQFDMBTT DPOTUSBJOU 
UVQMF     
BSJUZ     Ƈ
DPOTUSVDUPS  UZQFDMBTT EFDMBSBUJPO 
TZOUBY  
UZQF      UZQFDMBTT IJFSBSDIZ 
UZQF UZQFDMBTT JOIFSJUBODF 
DPODSFUF   
FSSPS    UZQFDMBTT JOTUBODF  
UZQF BMJBT   Ƈ Ƈ
UZQF BTTJHONFOU       
UZQF DPOTUBOU   
UZQF DPOTUSVDUPS   UZQFT WT UFSNT  
  
VODPOEJUJPOBM DBTF 
UZQF EFGBVMUJOH  Ƈ
VODVSSZ  
UZQF JOGFSFODF  
VOEFSTDPSF   
UZQF TJHOBUVSF   
  
 
VOJU 
UZQF TZOPOZN 
UZQF WBSJBCMF    WBMVF      
UZQFDMBTT        
    WBSJBCMF     
UZQFDMBTT WBSJBCMF
$)"15&3  '*/"- 130+&$5 

CPVOE    8BEMFS 1IJMJQ  


GSFF    8BMM    
XBSOJOH Ƈ
UZQF  
XBSOJOHT 
WBSJBCMFT
XFBL IFBE OPSNBM GPSN 
CPVOE 
XIFSF     
GSFF  
WJTJCJMJUZ  XIJUFTQBDF 

You might also like