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
ÐFS %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
ÐFS 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