Haskell Programming 0.12.0 Ereader PDF
Haskell Programming 0.12.0 Ereader PDF
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
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
%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
5ZQFT
5ZQFT
8IBU BSF UZQFT GPS
)PX UP SFBE UZQF TJHOBUVSFT
$VSSZJOH
1PMZNPSQIJTN
$0/5&/54 WJ
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
3FDVSTJPO
3FDVSTJPO
'BDUPSJBM
#PUUPN
'JCPOBDDJ OVNCFST
*OUFHSBM EJWJTJPO GSPN TDSBUDI
$IBQUFS &YFSDJTFT
%FƶOJUJPOT
-JTUT
-JTUT
5IF MJTU EBUBUZQF
$0/5&/54 WJJJ
5FTUJOH
5FTUJOH
" RVJDL UPVS PG UFTUJOH GPS UIF VOJOJUJBUFE
$POWFOUJPOBM UFTUJOH
&OUFS 2VJDL$IFDL
.PSTF DPEF
$0/5&/54 YJ
'VODUPS
'VODUPS
8IBUƊT B GVODUPS
$0/5&/54 YJJ
"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
.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
'PMEBCMF
$0/5&/54 YJW
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
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
/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
*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
"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
+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
"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
*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
)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
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
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
Ƒ :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
f = undefined
$0/5&/54 YMWJJ
%BOJFM 5BNNFUU
$)"15&3 "/:5)*/( '30. "-.045 /05)*/(
ԕ
Ӷ
ԕ
ӷ
ԕ
Ӹ
ԕ
ԍ
ԕ
Ԏ
ԕ
ԏ
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)*/(
ԕ ԧ
ԧ
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 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)*/(
λ 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
ᅶԧԧ
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
ᅶԧԧ
ᅶԧԧ
ᅶԧԧ
ᅶԨԨ
ᅶԧԧ
ᅶԨԨ
<ԧ ᅶԨԨ
>
ᅶԨԨ
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)*/(
ᅶԧԧ
ᅶԨԨ
ԩ
DBO CF SFXSJUUFO BT
ᅶԧԧ
ᅶԨԨ
ԩ
0OXBSE XJUI UIF SFEVDUJPO
ᅶԧԧ
ᅶԨԨ
ԩ
<ԧ ᅶԨԨ
>
ᅶԨԨ
ԩ
<Ԩ ԩ>
ԩ
'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 ԩ
ᅶ<ԧ ԩ>ԧԨ
ԩԨ
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
ᅶԧԨԧԨ
JT B DPOWFOJFOU TIPSUIBOE GPS UXP OFTUFE MBNCEBT POF GPS
FBDI BSHVNFOU
ԧ BOE Ԩ
ᅶԧ ᅶԨԧԨ
ᅶԧԧ
ᅶԧԧ
<ԧ >
ᅶԧԨԧԨ
$)"15&3 "/:5)*/( '30. "-.045 /05)*/(
ᅶԧԨԧԨ
ᅶԧ ᅶԨԧԨ
<ԧ >
ᅶԨԨ
<Ԩ >
ᅶԧԨԧԨ
ᅶԧԨԧԨ
ᅶԩԐ
ᅶԧ ᅶԨԧԨ
ᅶԩԐ
<ԧ ᅶԩԐ
>
ᅶԨ ᅶԩԐ
Ԩ
<Ԩ >
ᅶԩԐ
8F TUJMM DBO BQQMZ UIJT POF NPSF UJNF
$)"15&3 "/:5)*/( '30. "-.045 /05)*/(
Ԑ
ᅶԧԨԧԧԨ
ᅶԧԧԨ
ᅶԧԧԩ
ᅶԧԨԩԧԩ Ԩԩ
ᅶԜԝԜ
ᅶԟԟ
ᅶԧᅶԨᅶԩԧԩ Ԩԩ
ᅶԜᅶԝԜ
ᅶԟԟ
ᅶԨᅶԩ ᅶԜᅶԝԜ
ԩ Ԩԩ
ᅶԟԟ
ᅶԩ ᅶԜᅶԝԜ
ԩ
ᅶԟԟ
ԩ
ᅶԩ ᅶԝԩ
ᅶԟԟ
ԩ
ᅶԩԩ
*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)*/(
ᅶԧԨԧԩ
B
ᅶԧԩԧԩ
C
ᅶԜԝԜԩ
D
ᅶԩ ᅶԧԧԩ
ᅶԧԨԧԧԨ
B
ᅶԜԝԜԝԟ
C
ᅶԧ ᅶԨԧԨ
D
ᅶԐ ᅶԑԐԐԑ
ᅶԧԨԩԩԧ
B
ᅶԧ ᅶԨ ᅶԩԩ
C
ᅶԣԞԢԢԣ
D
ᅶԜԝԟԜԝ
$)"15&3 "/:5)*/( '30. "-.045 /05)*/(
$)"15&3 "/:5)*/( '30. "-.045 /05)*/(
$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
%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
ᅶԧԧԧ
ᅶԧԧԧ
<ԧ ᅶԧԧԧ
>ԧԧ
ᅶԧԧԧ
ᅶԧԧԧ
4VCTUJUVUJOH ᅶԧԧԧ
GPS FBDI PDDVSFODF PG ԧ 8FƊSF CBDL
UP XIFSF XF TUBSUFE BOE UIJT SFEVDUJPO QSPDFTT OFWFS FOET
ƈ XF DBO TBZ PNFHB EJWFSHFT
4VNNBSZ
5IF NBJO QPJOUT ZPV TIPVME UBLF BXBZ GSPN UIJT DIBQUFS BSF
ᅶԧԧԧԧ
ᅶԧԨԩԧ
ᅶԧԨԩԧԨ ԩԧ
ᅶԧԨԩԧԨ ԩԧԨ
ᅶԧԨԧԨ ԩԧԨ
ᅶԧԧԧԧ
ᅶԩԩԩ
ᅶԨԨԨ
ᅶԧԧԧԧ
ԩ
ᅶԐԑԒԒԑԐ
ԩԩ ᅶԦԥԦ
ᅶԧᅶԨԧԨԨ
ᅶԐԐ
ԑ
ᅶԨԨ
ᅶԧԧԧ
ᅶԩԩԠ
ᅶԩԩ
ᅶԩԩԩ
ᅶԩԩԨ
ᅶԧᅶԨԧԨԨ
ᅶԨԨ
Ԩ
ᅶԐԐԐ
ᅶԑԑԐ
Ԓ
ᅶԧԨԩԧԩ Ԩԩ
ᅶԧԩ
ᅶԧԐ
"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 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)*/(
ᅶԧԨԧԨ ԩԧԨ
JT OPU B DPNCJOBUPS
[ JT GSFF /PUF UIBU [ JTOƊU
CPVOE JO UIF IFBE
ᅶԩԩԩ
ᅶԨԨԨ
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 ԩԩԩ
ᅶԐԑԒԒԑԐ
ԩԩ ᅶԦԥԦ
ᅶԐᅶԑᅶԒԒԑԐ
ԩ
ԩ ᅶԦᅶԥԦ
ᅶԑᅶԒԒԑԩ
ԩ
ᅶԦᅶԥԦ
ᅶԒԒԩԩ
ᅶԦᅶԥԦ
ᅶԦᅶԥԦ
ԩ
ԩ
ᅶԥԩ
ԩ
ᅶԧᅶԨԧԨԨ
ᅶԐԐ
ԑ
ᅶԨ ᅶԐԐ
ԨԨ
ԑ
ᅶԐԐ
ԑ
ԑ
ԑԑ
ᅶԨԨ
ᅶԧԧԧ
ᅶԩԩԠ
ᅶԧԧԧ
ᅶԩԩԠ
ᅶԩԩԠ
ᅶԩԩԠ
ᅶԩԩԠ
Ԡ
ԠԠ
ᅶԩԩ
ᅶԩԩԩ
ᅶԩԩԨ
ᅶԩԩԩ
ᅶԩԩԨ
ᅶԩԩԨ
ᅶԩԩԨ
ᅶԩԩԨ
Ԩ
ԨԨ
ᅶԧᅶԨԧԨԨ
ᅶԨԨ
Ԩ
ᅶԨ ᅶԨԨ
ԨԨ
Ԩ
ᅶԨԨ
Ԩ
Ԩ
ԨԨ
$)"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
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
ᅶԧԐ
ԩ
%FƶOJUJPOT
5IF MBNCEB JO MBNCEB DBMDVMVT JT UIF HSFFL MFUUFS ᅶ VTFE
UP JOUSPEVDF
PS BCTUSBDU
BSHVNFOUT GPS CJOEJOH JO BO
FYQSFTTJPO
)FMMP )BTLFMM
.JLF )BNNPOE
$)"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
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
1
1 + 1
"Icarus"
Prelude> 1
1
Prelude> 1 + 2
3
$)"15&3 #"4*$ &913&44*0/4 "/% '6/$5*0/4
Prelude> (1 + 2) * 3
9
Prelude> ((1 + 2) * 3) + 100
109
'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
%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
triple x = x * 3
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
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
&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
1
"Icarus"
1 + 1
2 * 3 + 1
triple 2
triple 2
-- [triple x = x * 3; x:= 2]
2 * 3
6
(1, 2 + 2)
$)"15&3 #"4*$ &913&44*0/4 "/% '6/$5*0/4
half x = x / 2
square x = x * x
3.14 * (5 * 5)
3.14 * (10 * 10)
3.14 * (2 * 2)
3.14 * (4 * 4)
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
Prelude> 10 `div` 4
2
Prelude> div 10 4
2
1001.0
:info (*)
infixl 7 *
-- [1] [2] [3]
infixl 6 -
-- this
2 * 3 * 4
-- is evaluated as if it was
(2 * 3) * 4
-- Because of left-associativity from infixl
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
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)
Prelude> let y = 10
Prelude> let x = 10 * 5 + y
Prelude> let myResult = x * 5
Prelude> x
60
Prelude> y
10
Prelude> myResult
300
-- learn.hs
x = 10 * 5 + y
myResult = x * 5
y = 10
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
let
x = 3
y = 4
-- or
let x = 3
y = 4
/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
foo x =
let y = x * 2
z = x ^ 2
in 2 * y * z
x = 10
* 5 + y
myResult = x * 5
y = 10
Prelude> :l code/learn.hs
[1 of 1] Compiling Learn
/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
x = 10
* 5 + y
-- or
x = 10
* 5 + y
-- learn.hs
x = 10 * 5 + y
myResult = x * 5
y = 10
Prelude> :l code/learn.hs
[1 of 1] Compiling Learn
-- learn.hs
x = 10 * 5 + y
myResult = x * 5
y = 10
- learn.hs
x = 10 * 5 + y
myResult = x * 5
y = 10
/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
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
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
"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
'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.
(-3)*(-4) + (-2) == 10
10 == x == yeppers.
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
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
Prelude> mod (6 + 5) 7
4
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
-- but
'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
Prelude> 1000 + -9
<interactive>:3:1:
Precedence parsing error
cannot mix ‘+’ [infixl 6] and
prefix `-` [infixl 6]
in the same infix expression
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
f $ a = f a
$)"15&3 #"4*$ &913&44*0/4 "/% '6/$5*0/4
Prelude> (2^) (2 + 2)
16
-- can replace those parentheses
Prelude> (2^) $ 2 + 2
16
-- without either parentheses or $
Prelude> (2^) 2 + 2
6
8F DBO TFF GPS PVSTFMWFT XIZ UIJT DPEF EPFTOƊU NBLF TFOTF
JG XF FYBNJOF UIF SFEVDUJPO TUFQT
(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)!
(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
*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
Prelude> (1/) 2
0.5
Prelude> (/1) 2
2.0
Prelude> 2 - 1
1
Prelude> (-) 2 1
1
Prelude> (-2) 1
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
-- FunctionWithWhere.hs
module FunctionWithWhere where
Prelude> :l FunctionWithWhere.hs
$)"15&3 #"4*$ &913&44*0/4 "/% '6/$5*0/4
/PX XF IBWF UIF TBNF GVODUJPO
CVU VTJOH let JO UIF QMBDF
PG where
-- FunctionWithLet.hs
module FunctionWithLet where
<interactive>:6:1:
Not in scope: ‘printInc’
Perhaps you meant ‘printInc2’ (line 4)
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
DPVME CF SFXSJUUFO BT
Prelude> :l practice.hs
[1 of 1] Compiling Main
Ok, modules loaded: Main.
*Main> mult1
30
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
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
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
z = 7
x = y ^ 2
waxOn = x * 5
y = z + 8
10 + waxOn
-- or
(+10) waxOn
-- or
(-) 15 waxOn
-- or
(-) waxOn 15
let triple x = x * 3
triple waxOn
/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
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
4USJOHT
-JLF QVOOJOH
QSPHSBNNJOH JT B QMBZ PO
XPSET
"MBO 1FSMJT
$)"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
: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>
-- print2.hs
module Print2 where
main :: IO ()
main = do
putStrLn "Count to four for me:"
putStr "one, two"
putStr ", three, and"
putStrLn " four!"
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
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]
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
topLevelValue :: Integer
topLevelValue = 5
Prelude> :l TopOrLocal.hs
[1 of 1] Compiling TopOrLocal
Ok, modules loaded: TopOrLocal.
*TopOrLocal> topLevelFunction 5
20
&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
Prelude> let f = 3
Prelude> let g = 6 * f + h
area d = pi * (r * r)
r = d / 2
area d = pi * (r * r)
where r = d / 2
-- but
<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
++ [1, 2, 3] [4, 5, 6]
-- 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
Prelude> :i (++)
(++) :: [a] -> [a] -> [a] -- Defined in ‘GHC.Base’
infixr 5 ++
-- print3broken.hs
module Print3Broken where
printSecond :: IO ()
printSecond = do
putStrLn greeting
main :: IO ()
main = do
putStrLn greeting
printSecond
where greeting = "Yarrrrr"
Prelude> :l print3broken.hs
[1 of 1] Compiling Print3Broken ( print3broken.hs, interpreted
Prelude> :t 'c'
'c' :: Char
Prelude> :t "c"
"c" :: [Char] -- List of Char is String, same thing.
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]]
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
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!"
thirdLetter ::
thirdLetter x =
main :: IO ()
main = print ()
$)"15&3 4*.1-& 01&3"5*0/4 8*5) 5&95
%FƶOJUJPOT
" 4USJOH JT B TFRVFODF PG DIBSBDUFST *O )BTLFMM
String JT
SFQSFTFOUFE CZ B MJOLFEMJTU PG Char WBMVFT
BLB [Char]
#BTJD EBUBUZQFT
3PCJO .JMOFS
$)"15&3 #&$"64& 1*(4 $"/Ɗ5 '-:
Prelude> :t not
not :: Bool -> Bool
#VU XIFO XF VTF UIF not GVODUJPO
XF VTF UIF EBUB DPOTUSVD
UPST
PS WBMVFT
Integer 5IJT UZQF JT BMTP GPS JOUFHFST
CVU UIJT POF TVQQPSUT
BSCJUSBSJMZ MBSHF PS TNBMM
OVNCFST
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
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 '-:
<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
Prelude> :i Int
data Int = GHC.Types.I# GHC.Prim.Int#
instance Bounded Int -- Defined in ‘GHC.Enum’
'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 '-:
Prelude> :t (/)
(/) :: Fractional a => a -> a -> a
Prelude> 1 / 2
0.5
Prelude> 4 / 2
2.0
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
Prelude> :t (==)
$)"15&3 #&$"64& 1*(4 $"/Ɗ5 '-:
False
Prelude> 'a' == 'A'
False
Prelude> "Julie" == "Chris"
False
" EBUBUZQF UIBU IBT OP JOTUBODF PG Ord XJMM OPU XPSL XJUI
UIFTF GVODUJPOT
<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 '-:
Prelude> "Julie" == 8
<interactive>:38:12:
No instance for (Num [Char]) arising from
the literal ‘8’
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 '-:
/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
-- && 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
not (x = 6)
(1 * 2) > 5
if CONDITION
then EXPRESSION\_A
else EXPRESSION\_B
Prelude> let x = 0
Prelude> if (x + 1 == 1) then "AWESOME" else "wut"
"AWESOME"
-- Given:
x = 0
"AWESOME"
-- dunzo
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 '-:
-- greetIfCool1.hs
module GreetIfCool1 where
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.
-- greetIfCool2.hs
module GreetIfCool2 where
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 '-:
λ> (,) 8 10
(8,10)
λ> (,) 8 "Julie"
(8,"Julie")
λ> (,) True 'c'
(True,'c')
λ> (,) 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
"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> :t myTup
myTup :: (Integer, [Char])
Prelude> fst myTup
1
Prelude> snd myTup
"blah"
Prelude> import Data.Tuple
Prelude> swap myTup
("blah",1)
-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> :t awesome
awesome :: [[Char]]
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]
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 '-:
Prelude> 6 / 3
-- and
Prelude> 6 / length [1, 2, 3]
Prelude> let x = 5
Prelude> x + 3 == 5
$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
x = (+)
F xs = w 'x' 1
where w = length xs
\ 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
B
show a => a -> String
C
Show a -> a -> String
D
Show a => a -> String
B
a -> a -> Bool
C
Eq a => a -> a -> Bool
D
Eq a -> a -> a -> Bool
E
Eq a => A -> Bool
B
(a, b) -> a
C
b -> a
D
(a, b) -> b
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
Prelude> :t Cat
Cat :: Pet
Prelude> :t Dog
Dog :: Name -> Pet
id :: a -> a
id x = x
$)"15&3 #&$"64& 1*(4 $"/Ɗ5 '-:
5ZQFT
$)"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
Prelude> :type 13
13 :: Num a => a
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
5IF ƶSTU QBSBNFUFS PG fst IBT UIF UZQF (a, b) /PUF UIBU
UIF UVQMF UZQF JUTFMG (,) UBLFT UXP BSHVNFOUT Ԑ BOE ԑ IFSF
5IF SFTVMU PG UIF GVODUJPO
XIJDI IBT UZQF Ԑ *UƊT UIF TBNF
Ԑ UIBU XBT JO UIF UVQMF (a, b)
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
-- or
)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
'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
f :: a -> a -> a
-- associates to
f :: a -> (a -> a)
BOE
-- associates into
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
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
Prelude> :t subtractOne
subtractOne :: Integer -> Integer
Prelude> let result = subtractOne 11
Prelude> result
-20
curriedFunction :: Integer
-> Bool
-> Integer
curriedFunction i b =
i + (nonsense b)
$)"15&3 5:1&4
anonNested :: Integer
-> Bool
-> Integer
anonNested =
\i -> \b -> i + (nonsense b)
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
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
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
: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-
True
Prelude> let c = (`elem` [1..10])
Prelude> c 9
True
Prelude> c 25
False
*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
B
Char -> Char -> Char
C
x -> x -> x -> x
D
a -> a -> a
E
a -> a -> a -> Char
B
String
C
Char -> String
D
Int
E
Char
B
Double
C
Integer
D
Integral b => b
E
Num b => b
B
Integer
C
Fractional b => b
D
Double
E
Num b => b
B
[Char]
C
Eq b => b
D
b -> [Char]
E
b
$)"15&3 5:1&4
F
Eq b => b -> [Char]
B
b
C
Eq b => b
D
[Char]
E
b -> [Char]
F
Eq b => b -> [Char]
B
Integer
C
Int
D
a
E
(Num a, Ord a) => a
F
Ord a => a
G
Num a => a
B
(Num a, Ord a) => a
C
Int
D
a
E
Num a => a
F
Ord a => a
G
Integer
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
id :: a -> a
-- For all 'a', get an argument of some type 'a',
-- return value of same type 'a'
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
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
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
5IBU XPSLT KVTU ƶOF 8IZ -FUƊT MPPL BU UIF UZQFT BOE TFF JG
XF DBO ƶOE PVU
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
)FSF XF MFU ()$J JOGFS UIF UZQF PG ourId JUTFMG %VF UP BMQIB
FRVJWBMFODF
UIF EJƵFSFODF JO MFUUFST ԣ IFSF WFSTVT Ԑ BCPWF
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
-- typeInference1.hs
module TypeInference1 where
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
-- typeInference2.hs
module TypeInference2 where
f x y = x + y + 3
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
-- General function
(*) :: Num a => a -> a -> a
-- Applied to a value
myMult x = (x / 3) * 5
)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
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
triple x = tripleItYo x
where tripleItYo :: Integer -> Integer
tripleItYo y = y * 3
Prelude> :t triple
triple :: Integer -> Integer
.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
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
B
UBLFT POF BSHVNFOU
C
SFUVSOT POF FMFNFOU PG UZQF Ԑ GSPN B MJTU
D
NVTU SFUVSO BO Int WBMVF
E
JT DPNQMFUFMZ ƶDUJPOBM
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
-- simple example
example = 1
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
(JWFO
x = 5
y = x + 5
z y = y * 10
(JWFO
x = 5
y = x + 5
f = 4 / y
(JWFO
x = "Julie"
y = " <3 "
z = "Haskell"
f = x ++ y ++ z
%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
f :: f -> g -> C
functionH ::
functionH (x:_) = x
functionC ::
functionC x y = if (x > y) then True else False
functionS ::
functionS (x, y) = y
myFunc :: (x -> y)
-> (y -> z)
-> c
-> (a, x)
-> (a, z)
myFunc xToY yToZ _ (a, x) = undefined
myFunc :: (x -> y)
-> (y -> z)
-> c
-> (a, x)
-> (a, z)
myFunc xToY yToZ _ (a, x) =
(a, (yToZ (xToY x)))
i :: a -> a
i = undefined
c :: a -> b -> a
c = 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
/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
data Woot
data Blah
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
%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
id :: a -> a
id :: a -> a
f :: a -> 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
5ZQFDMBTTFT
.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
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
instance Ord Bool Ƈ Ord GPS UIJOHT UIBU DBO CF QVU JOUP B
TFRVFOUJBM PSEFS
&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.
-- 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.
(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.
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.
&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
data Trivial =
Trivial
data Trivial =
Trivial'
-FUƊT ESJMM EPXO B CJU JOUP IPX UIJT JOTUBODF TUVƵ XPSLT
$)"15&3 -&44 "%)0$ 10-:.031)*4.
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
/PX XFƊMM XSJUF BO Eq JOTUBODF GPS PVS Date UZQF 5IJT POF JT
NPSF JOUFSFTUJOH
$)"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
data DayOfWeek =
Mon | Tue | Weds | Thu | Fri | Sat | Sun
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.
CVU JUƊT BMTP B DPODFSO XJUI BOZ GVODUJPO UIBU EPFTOƊU IBOEMF
BMM QPTTJCMF JOQVUT
TVDI BT
*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
data Identity a =
Identity a
In the expression:
Identity NoEqInst == Identity NoEqInst
5IBU XJMM DPNQJMF
CVU JUƊT OPU DMFBS XIZ ZPVƊE EP JU .BZCF
ZPV IBWF ZPVS PXO TFDSFU SFBTPOT
*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.
*OUFHSBM
5IF UZQFDMBTT DBMMFE Integral IBT UIF GPMMPXJOH EFƶOJUJPO
'SBDUJPOBM
Num JT B TVQFSDMBTT PG Fractional 5IF Fractional UZQFDMBTT JT
EFƶOFE BT GPMMPXT
divideThenAdd x y = (x / y) + 1
8FƊMM MPBE UIJT XJUI B UZQF UIBU BTLT POMZ GPS B Num JOTUBODF
Prelude> 1 / 2
0.5
Prelude> 1 / 2 :: Float
0.5
Prelude> 1 / 2 :: Double
0.5
Prelude> 1 / 2 :: Rational
1 % 2
Num
Real
FUD BSF UZQFDMBTTFT
BOE Integer BOE Double BSF
UIF UZQFT UIFZ EFGBVMU UP 5IJT UZQF EFGBVMUJOH GPS Fractional
NFBOT UIBU
DIBOHFT UP
JG ZPV EPOƊU TQFDJGZ UIF DPODSFUF UZQF EFTJSFE GPS (/) "
TJNJMBS FYBNQMF CVU GPS Integral XPVME CF
EFGBVMUJOH UP
/PX XF DBO NBLF UIJT UZQF NPSF TQFDJƶD
BOE UIF QSPDFTT
$)"15&3 -&44 "%)0$ 10-:.031)*4.
let x = 10 :: Integer
let y = 5 :: Integer
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.
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
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
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"
*G ZPV USZ UP HJWF JU UPP GFX BSHVNFOUT
ZPV XJMM HFU UIJT
TUSBOHFTFFFNJOH NFTTBHF
-- [4]
In a stmt of an interactive GHCi command: print it
-- [ 5 ]
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.
data DayOfWeek =
Mon | Tue | Weds | Thu | Fri | Sat | Sun
deriving (Eq, Show)
*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
compare (3 * 4) (3 * 5)
(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> 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"
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.
Prelude> :t print
print :: Show a => a -> IO ()
*Main> Blah
Blah
"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-
Ƒ UIF JOTUBODFT TQFDJGZ UIF XBZT UIBU UZQF VTFT UIF GVODUJPOT
PG UIF UZQFDMBTT
newtype Year =
Year Integer
deriving (Eq, Show)
/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> :t sumNumberish
sumNumberish :: Numberish a => a -> a -> a
Prelude> defaultNumber
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
+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
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.
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.
B
JODMVEFT BMM UZQFT JO )BTLFMM
C
JT UIF TBNF BT UIF 0SE DMBTT
D
NBLFT FRVBMJUZ UFTUT QPTTJCMF
E
POMZ JODMVEFT OVNFSJD UZQFT
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
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
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.
printIt :: IO ()
printIt = putStrLn (show x)
)FSFƊT UIF UZQF FSSPS ZPV HFU JG ZPV USZ UP MPBE UIF DPEF
settleDown x = if x == Woot
then Blah
else x
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
data Sentence =
Sentence Subject Verb Object
deriving (Eq, Show)
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.
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
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
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
C
signifier :: Ord a => [a] -> a
: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
(FSBME 4VTTNBO
$)"15&3 .03& '6/$5*0/"- 1"55&3/4
%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
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
Prelude> :t myVal
myVal :: t -> Integer
addOne 10 -- x is bound to 10
addOne 10 = 10 + 1
= 11
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
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
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
B
Integer -> Integer -> Integer
C
Num a => a -> a -> a -> a
D
Num a => a -> a
E
Num a => a -> a -> a
addOne x = x + 1
*OUP
addOne = \x -> x + 1
B
3FXSJUF UIF f GVODUJPO JO UIF XIFSF DMBVTF
C
3FXSJUF UIF GPMMPXJOH UP VTF BOPOZNPVT MBNCEB TZO
UBY
: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
<interactive>:9:33: Warning:
Pattern match(es) are overlapped
In an equation for ‘isItTwo’: isItTwo 2 = ...
Prelude> isItTwo 2
False
Prelude> isItTwo 3
False
/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
Prelude> isItTwo 2
True
Prelude> isItTwo 3
*** Exception: :50:33-48:
Non-exhaustive patterns
in function isItTwo
<interactive>:28:5: Warning:
$)"15&3 .03& '6/$5*0/"- 1"55&3/4
<interactive>:28:5: Warning:
Pattern match(es) are non-exhaustive
In an equation for ‘isItTwo’:
-- registeredUser1.hs
module RegisteredUser where
-- registeredUser2.hs
module RegisteredUser where
/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
data WherePenguinsLive =
Galapagos
| Antarctica
| Australia
| SouthAfrica
| SouthAmerica
deriving (Eq, Show)
data Penguin =
Peng WherePenguinsLive
deriving (Eq, Show)
8IFO ZPV EJE UIBU FYFSDJTF
ZPV NBZ IBWF XSJUUFO JU MJLF
UIJT
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
Prelude> :l code/matchingTuples1.hs
[1 of 1] Compiling TupleFunctions
Ok, modules loaded: TupleFunctions.
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
funcZ x =
case x + 1 == 1 of
True -> "AWESOME"
False -> "wut"
$)"15&3 .03& '6/$5*0/"- 1"55&3/4
pal xs =
case xs == reverse xs of
True -> "yes"
False -> "no"
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
5IF OFYU FYFSDJTF EPFTOƊU IBWF BMM UIF DBTFT DPWFSFE 4FF
JG ZPV DBO ƶY JU
nums x =
case compare x 0 of
LT -> -1
GT -> 1
Prelude> :t flip
flip :: (a -> b -> c) -> b -> a -> c
)PXFWFS UIJT XJMM OPU XPSL 5IJT JT OPU IPX -> BTTPDJBUFT
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
dodgy x y = x + y * 10
oneIsOne = dodgy 1
oneIsTwo = (flip dodgy) 2
Prelude> dodgy 1 0
1
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 <condition>
then <result if True>
else <result if False>
Prelude> let x = 0
Prelude> if (x + 1 == 1) then "AWESOME" else "wut"
"AWESOME"
-- alternately
Prelude> let x = 0
Prelude> :{
Prelude| if (x + 1 == 1)
Prelude| then "AWESOME"
Prelude| else "wut"
Prelude| :}
"AWESOME"
Prelude> let x = 0
Prelude> :{
Prelude| if (x + 1 == 1)
Prelude| then "AWESOME"
Prelude| else "wut"
Prelude| :}
"AWESOME"
/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
"OE UIF GPMMPXJOH GVODUJPO XJMM UBLF ZPVS EPHƊT BHF BOE UFMM
ZPV IPX PME ZPVS EPH JT JO IVNBO ZFBST
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
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
JT B GVODUJPO GSPN Ԑ UP ԑ
*O &OHMJTI
HJWFO B GVODUJPO ԑ UP Ԓ
HJWFO B GVODUJPO Ԑ UP ԑ
SFUVSO B GVODUJPO Ԑ UP Ԓ
$)"15&3 .03& '6/$5*0/"- 1"55&3/4
(f . g) x = f (g x)
"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ƍ
(f . g) x = f (g x)
f . g = \x -> f (g x)
$)"15&3 .03& '6/$5*0/"- 1"55&3/4
f . g . h = \x -> f (g (h x))
BT B QPJOUGSFF GVODUJPO
-- arith2.hs
module Arith2 where
main :: IO ()
main = do
print (0 :: Int)
print (add 1 0)
print (addOne 0)
print (addOnePF 0)
print ((addOne . addOne) 0)
(.) :: (b -> c)
-- (String -> IO ())
-> (a -> b)
-- (a -> String)
-> a -> c
-- a -> IO ()
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
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
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
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
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
...
/PUJDF B QBUUFSO
-- arith4.hs
module Arith4 where
-- id :: a -> a
-- id x = x
main = do
print (roundTrip 4)
print (id 4)
blah :: Int
blah = 10
\x -> x
-- anonymous version of id
id x = x
-- not anonymous, it's bound to 'id'
f a b = a + b
-- is equivalent to
data Identity a =
Identity a
deriving (Eq, Show)
data Product a b =
Product a b
deriving (Eq, Show)
data SumOfThree a b c =
FirstPossible a
| SecondPossible b
| ThirdPossible c
deriving (Eq, Show)
$)"15&3 .03& '6/$5*0/"- 1"55&3/4
-- morally equivalent to
-- is actually
-- or
-- can be implemented as
comp :: (b -> c) -> ((a -> b) -> (a -> c))
comp f g x = f (g x)
-- not pointfree
blah x = x
addAndDrop x y = x + 1
reverseMkTuple a b = (b, a)
reverseTuple (a, b) = (b, a)
5P TFF NPSF FYBNQMFT MJLF UIJT
DIFDL PVU UIF )BTLFMM 8JLJ
QBHF PO 1PJOUGSFF BU https://wiki.haskell.org/Pointfree
3FDVSTJPO
$)"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
'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
4! = 4 * 3 * 2 * 1
12 * 2 * 1
24 * 1
24
4! = 24
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
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
-- Changes to
-- n = n * factorial (n - 1)
factorial 4 = 4 * factorial (4 - 1)
Ƒ UP SFQISBTF JO DPEF
(.) f g = \x -> f (g x)
Prelude> incTimes 10 0
10
Prelude> incTimes 5 0
5
Prelude> incTimes 5 5
10
*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>
Prelude> f False
0
Prelude> f True
*** Exception: blah
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
" 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
/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
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
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
*Main> fibonacci 6
9
8IZ #FDBVTF
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
*Main> fibonacci 6
8
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
FWFO BEE TPNF UZQF TZOPOZNT UIBU XPOƊU DIBOHF ZPVS DPEF
-- changes to
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
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
dividedBy 10 2
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
B
Bool
C
NPTUMZ True
D
[a]
E
[[Bool]]
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!"]
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
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
frappe "1"
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
'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
Prelude> div 10 2
5
Prelude> div 10 (-2)
-5
Prelude> div (-10) (-2)
5
Prelude> div (-10) (2)
-5
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
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
"MTP DPOTJEFS
)FSF JT XIBU ZPVS PVUQVU TIPVME MPPL JO UIF 3&1- XIFO JUƊT
XPSLJOH
%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
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
data [] a = [] | a : [a]
data [] a = [] | a : [a]
-- [1] [2] [3] [4] [5] [6]
OVMMBSZ DPOTUSVDUPS []
$)"15&3 5)*4 5)*/( "/% 40.& .03& 456''
PS JU DBO CF DPOTUSVDUFE CZ
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''
3BUIFS UIBO
Prelude> (1 : 2 : 3 : []) ++ 4 : []
[1,2,3,4]
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"
Prelude> enumFromTo 3 1
[]
Prelude> enumFromTo 1 3
[1,2,3]
&YFSDJTF &OVN'SPN5P
4PNF UIJOHT ZPVƊMM XBOU UP LOPX BCPVU UIF Enum UZQFDMBTT
Prelude> take 3 []
[]
[10,11,12,13,14,15,16,17,18,19]
Prelude> drop 4 []
[]
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 []
([],[])
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
[]
-- 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
-- Implement this
myLines :: String -> [String]
myLines = undefined
"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^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''
/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> :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''
(JWFO UIF BCPWF XIBU EP ZPV UIJOL UIJT GVODUJPO XPVME EP
1 : 2 : 3 : []
or
1 : (2 : (3 : []))
:
/ \
1 :
/ \
$)"15&3 5)*4 5)*/( "/% 40.& .03& 456''
2 :
/ \
3 []
: <------|
/ \ |
_ : <----| This is the "spine"
/ \ |
_ : <--|
/ \
_ []
blah = _
(1, 1 + 1)
"Papu" ++ "chon"
:
/ \
_ _
:
/ \
_ :
/ \
_ :
/ \
$)"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
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
: <-|
/ \ |
|-> _ : <-|
| / \ | These got evaluated (forced)
|-> _ : <-|
| / \ |
|-> _ [] <-|
|
| These did not
15
OFJUIFS
[1, 2, 3, 4, 5]
1 : 2 : 3 : 4 : _
enumFromTo 1 10
length [1, 2, 3, 4, 5]
['a'..'m'] ++ ['n'..'z']
(_, 'b')
$)"15&3 5)*4 5)*/( "/% 40.& .03& 456''
map (+1)
-- (a -> b) becomes more specific,
-- is resolved to: Num a => a -> a
fmap (+1)
-- again, (a -> b) is now more specific
-- Now we reduce
2 : ((+1) 2 : ((+1) 3 : []))
2 : 3 : (+1) 3 : []
2 : 3 : 4 : [] == [2, 3, 4]
map f [1, 2, 3] == [f 1, f 2, f 3]
:
/ \
1 :
/ \
2 :
/ \
3 []
:
/ \
(+1) 1 :
/ \
(+1) 2 :
/ \
(+1) 3 []
$)"15&3 5)*4 5)*/( "/% 40.& .03& 456''
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]
"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
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]]
-FUƊT OPX UBLF B DMPTFS MPPL BU filter filter IBT UIF GPMMPX
JOH EFƶOJUJPO
8F IBWF TFFO IPX filter XPSLT XJUI odd BOE even BMSFBEZ
8F IBWF BMTP TFFO POF FYBNQMF BMPOH UIF MJOFT PG UIJT
"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
"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
Prelude> :t zip
zip :: [a] -> [b] -> [(a, b)]
0OF UIJOH UP OPUF JT UIBU zip TUPQT BT TPPO BT POF PG UIF MJTUT
SVOT PVU PG WBMVFT
;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''
%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
$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''
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
*NQMFNFOU myReverse
SBUIFS UIBO
%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
1 : [2, 3]
-- [a] [b]
[1, 2, 3]
-- [c]
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''
data [] a = [] | a : [a]
-- ^ cons operator
-- Defining it ourselves
)FSF (Cons 1 ...)
(Cons 2 ...) BOE (Cons 3 Nil) BSF BMM
JOEJWJEVBM DPOT DFMMT JO UIF MJTU [1, 2, 3]
_ : ----------|
(_ : -------|
(_ : ----> Spine
[]))
'PMEJOH MJTUT
Ð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
'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
1 + (2 + (3 + 0))
*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
)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]
(+) 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*(".*
-- 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
*OUP
1 + (2 + (3 + 0))
1 + (2 + (3 + 0))
1 + (2 + 3)
1 + 5
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
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*(".*
8F DBO BMTP VTF UIF TBNF USJDL XF VTFE UP TFF UIF BTTPDJB
UJWJUZ PG foldr UP TFF UIF BTTPDJBUJWJUZ PG foldl
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
[15,14,12,9,5,0]
&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
[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))
5IJT UJNF XF DBO TFF DMFBSMZ UIBU XF HPU EJƵFSFOU SFTVMUT
BOE
$)"15&3 %"5" 4536$563& 03*(".*
-- foldr f z [1, 2, 3]
-- f ~ (:); z ~ []
-- Run it in your REPL. It'll return True.
foldr (:) [] (1 : 2 : 3 : []) == 1 : (2 : (3 : []))
foldl f z [1, 2, 3]
-- f ~ (:); z ~ []
-- (((z `f` 1) `f` 2) `f` 3)
((([] : 1) : 2) : 3)
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*(".*
/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*(".*
B
flip (*) 1 [1..5]
C
foldl (flip (*)) 1 [1..5]
D
foldl (*) 1 [1..5]
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
B
SFEVDF TUSVDUVSF
C
FYQBOE TUSVDUVSF
D
SFOEFS ZPV DBUBUPOJD
E
HFOFSBUF JOƶOJUF EBUB TUSVDUVSFT
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
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]
/PX DPNQBSF
*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
Prelude> "" == []
True
Prelude> :t ""
"" :: [Char]
Prelude> :t []
[] :: [t]
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
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> :{
*Prelude| let f a b = take 3
*Prelude| (a :: String) ++
*Prelude| (b :: String)
*Prelude| :}
Prelude> foldr f "" pab
"PizAppBan"
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])
import Data.Time
theDatabase :: [DatabaseItem]
theDatabase =
[ DbDate (UTCTime
(fromGregorian 1911 5 1)
(secondsToDiffTime 34123))
, DbNumber 9001
, DbString "Hello, world!"
, DbDate (UTCTime
(fromGregorian 1921 5 1)
(secondsToDiffTime 34123))
]
)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
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
GPMEM
4FMGDBMMT UBJMDBMM
UISPVHI UIF MJTU
POMZ CFHJOOJOH UP
QSPEVDF WBMVFT BǒFS JUƊT SFBDIFE UIF FOE PG UIF MJTU
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
-- evaluating additions
= [1, 2, 4, 7]
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*(".*
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
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
seekritFunc x =
div (sum (map length (words x)))
(length (words x))
myFunc = foldr f z
-- fold, both myAnd and the folding function are point-free now
myAnd :: [Bool] -> Bool
myAnd = foldr (&&) True
$)"15&3 %"5" 4536$563& 03*(".*
%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*(".*
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.
f x y z = h (subFunction x y z)
where subFunction x y z = g x y z
f x y z = h (f (x - 1) y z)
f x y z = f (x - 1) y z
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
$)"15&3 %"5" 4536$563& 03*(".*
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
"MHFCSBJD EBUBUZQFT
$)"15&3 36-& 5)& 5:1&4
36-& 5)& 6/*7&34&
Ƒ JOUSPEVDF LJOET
data [] a = [ ] | a : [a]
-- [ 7 ] [8] [9]
data [] a = [] | a : [a]
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
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&
myHusky :: HuskyType a
myHusky = HuskyData
data Doggies a =
Husky a
| Mastiff a
deriving (Eq, Show)
/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
data Price =
-- (a)
Price Integer deriving (Eq, Show)
-- (b) [1]
data Manufacturer =
-- (c)
Mini
-- (d)
| Mazda
-- (e)
| Tata
-- (f)
deriving (Eq, Show)
data Airline =
-- (g)
PapuAir
-- (h)
| CatapultsR'Us
-- (i)
| TakeYourChancesUnited
-- (j)
deriving (Eq, Show)
/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&
&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
"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
-- nullary
data Example0 =
Example0 deriving (Eq, Show)
-- unary
data Example1 =
Example1 Int 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
5ZQF DPOTUSVDUPS
%FSJWJOH DMBVTF
&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
'PS UIJT POF SFDBMM UIBU Bool JT BMTP EFƶOFE XJUI UIF |
data Airline =
PapuAir
| CatapultsR'Us
| TakeYourChancesUnited
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
Prelude> :t False
False :: Bool
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
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
newtype Goats =
Goats Int deriving (Eq, Show)
newtype Cows =
Cows Int deriving (Eq, Show)
: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&
newtype Goats =
Goats Int deriving (Eq, Show, TooMany)
data BigSmall =
Big Bool
| Small Bool
deriving (Eq, Show)
(JWFO B EBUBUZQF
$)"15&3 36-& 5)& 5:1&4
36-& 5)& 6/*7&34&
data NumberOrBool =
Numba Int8
| BoolyBool Bool
deriving (Eq, Show)
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
data TwoQs =
MkTwoQs QuantumBool QuantumBool
deriving (Eq, Show)
$)"15&3 36-& 5)& 5:1&4
36-& 5)& 6/*7&34&
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 =
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
5
Prelude> name papu
"Papu"
2 * (3 + 4)
2 * (7)
14
2 * 3 + 2 * 4
(6) + (8)
$)"15&3 36-& 5)& 5:1&4
36-& 5)& 6/*7&34&
14
a * (b + c) -> (a * b) + (a * c)
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
data Author =
Fiction AuthorName
| Nonfiction AuthorName
deriving (Eq, Show)
data Expr =
Number Int
| Add Expr Expr
| Minus Expr
| Mult Expr Expr
| 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&
data Garden =
Garden Gardener FlowerType
deriving Show
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)
newtype NumCow =
NumCow Int
deriving (Eq, Show)
newtype NumPig =
NumPig Int
deriving (Eq, Show)
data Farmhouse =
Farmhouse NumCow NumPig
deriving (Eq, Show)
newtype NumSheep =
NumSheep Int
deriving (Eq, Show)
data BigFarmhouse =
BigFarmhouse NumCow NumPig NumSheep
deriving (Eq, Show)
type BigFarmhouse' =
Product NumCow (Product NumPig NumSheep)
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)
-- Getting it right
Prelude> let bess = First (CowInfo "Bess" 4) :: Animal'
-- Making a mistake
Prelude> let elmo' = Second (SheepInfo "Elmo" 5 5)
Prelude> let elmo = First elmo' :: Animal'
"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
data Id a =
MkId a deriving (Eq, Show)
-- note:
-- MkId :: a -> Id a
idInt :: Id Integer
idInt = MkId 10
idIdentity :: Id (a -> a)
idIdentity = MkId $ \x -> x
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)
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
Prelude> :t RecordProduct
RecordProduct :: a -> b -> RecordProduct a b
Prelude> :t Product
Product :: a -> b -> Product a b
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)
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 }
&YFSDJTF 1SPHSBNNFST
allOperatingSystems :: [OperatingSystem]
allOperatingSystems =
[ GnuPlusLinux
, OpenBSDPlusNevermindJustBSDStill
, Mac
, Windows
]
allLanguages :: [ProgrammingLanguage]
allLanguages = [Haskell, Agda, Idris, PureScript]
allProgrammers :: [Programmer]
allProgrammers = undefined
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
Prelude> partialAf
Programmer {os = GnuPlusLinux, lang =
*** Exception:
Missing field in record construction lang
data ThereYet =
There Integer Float String Bool
deriving (Eq, Show)
yusssss :: ThereYet
yusssss = notQuite False
There :: Integer -> Float -> String -> Bool -> ThereYet
nope :: Float -> String -> Bool -> ThereYet
notYet :: String -> Bool -> ThereYet
notQuite :: Bool -> ThereYet
yusssss :: ThereYet
%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&
-- FarmerType is a Sum
data FarmerType = DairyFarmer
| WheatFarmer
| SoybeanFarmer deriving Show
data FarmerRec =
FarmerRec { name :: Name
, acres :: Acres
, farmerType :: FarmerType } deriving Show
-- Don't.
a -> b -> c
(c ^ b) ^ a
c ^ (b * a)
data Quantum =
Yes
| No
| Both
deriving (Eq, Show)
-- 3 + 3
quantSum1 :: Either Quantum Quantum
quantSum1 = Right Yes
-- 3 * 3
quantProd1 :: (Quantum, Quantum)
quantProd1 = (Yes, Yes)
-- 3 ^ 3
data Quad =
One
| Two
| Three
| Four
deriving (Eq, Show)
-- in GHCi
Prelude> :kind Silly
Silly :: * -> * -> * -> * -> *
-- Identical to (a, b, c, d)
Prelude> :kind (,,,)
(,,,) :: * -> * -> * -> * -> *
data EsResultFound a =
EsResultFound { _version :: DocVersion
, _source :: a
} deriving (Eq, Show)
B HJWFO DPOUFYU
DPOTUSBJO UIF WBSJBCMF JO UIF UZQF TJHOBUVSF T
"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
data Product a b =
a :&: b
deriving (Eq, Show)
Prelude> 1 :&: 2
1 :&: 2
Prelude> :t 1 :&: 2
1 :&: 2 :: (Num a, Num b) => Product a b
/JM FNQUZ MJTU WBMVF XIJDI BMTP NBSLT UIF FOE PG B MJTU
-- from GHCi
Prelude> let nil = Nil
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&
data BinaryTree a =
Leaf
| Node (BinaryTree a) a (BinaryTree a)
deriving (Eq, Ord, Show)
mapExpected =
Node (Node Leaf 4 Leaf) 2 (Node Leaf 5 Leaf)
Prelude> :t Node
Node :: BinaryTree a -> a -> BinaryTree a -> BinaryTree a
f :: (a -> b)
left :: BinaryTree a
a :: a
right :: BinaryTree a
" GFX TVHHFTUJPOT UIBU NJHIU IFMQ ZPV XJUI UIJT FYFSDJTF
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&
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&
B
f :: [Char]
C
f :: String -> String
D
f :: Weekday -> String
E
f :: Day -> Beer
B
NVTU IBWF BU MFBTU POF BSHVNFOU
C
NVTU CFHJO XJUI B DBQJUBM MFUUFS
D
NVTU CF QPMZNPSQIJD
E
DBOOPU CF JNQPSUFE GSPN NPEVMFT
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
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
Prelude> f (1, 2)
1
(1,2)
Prelude> doubleUp []
[]
Prelude> doubleUp [1]
[1,1]
Prelude> doubleUp [1, 2]
[1,1,2]
Prelude> doubleUp [1, 2, 3]
[1,1,2,3]
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
-BOHVBHF FYFSDJTFT
8SJUF B GVODUJPO UIBU DBQJUBMJ[FT B XPSE
&YBNQMF PVUQVU
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'
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
cellPhonesDead :: DaPhone
-> String
-> [(Digit, Presses)]
cellPhonesDead = 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&
8IBU XBT UIF NPTU QPQVMBS MFUUFS PWFSBMM 8IBU XBT UIF
NPTU QPQVMBS XPSE
)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&
data Expr
= Lit Integer
| Add Expr Expr
&YQFDUFE PVUQVU
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
ÐFS 8 %JKLTUSB
$)"15&3 4*(/"-*/( "%7&34*5:
Ƒ IJHIFSLJOEFEOFTT
<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
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
SFTVMU
5IFO XF DBO TFF XIBU UIJT EPFT GPS VT XIFO EFBMJOH XJUI
CBE EBUB
/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:
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
Ƒ *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:
5IF SFTU PG PVS IFMQFS GVODUJPO mkPerson' BSF KVTU QMBJO PME
QBUUFSO NBUDIFT
/PX MFUƊT TFF XIBU XF HFU
"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)
Prelude> :k Char
Char :: *
Prelude> :k (,)
(,) :: * -> * -> *
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 :: *
Prelude> :k Either
Either :: * -> * -> *
Prelude> :k Maybe
Maybe :: * -> *
Prelude> :k Int
Int :: *
Prelude> :k Bool
Bool :: *
/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] :: *
Prelude> :k Maybe []
*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
"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
*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
<interactive>:53:1:
No instance for (Show (t0 -> t0))
...
id :: a -> a
$)"15&3 4*(/"-*/( "%7&34*5:
r :: a -> f a
4USJOH QSPDFTTJOH
#FDBVTF UIJT JT UIF LJOE PG UIJOH MJOHVJTUT BIFN FOKPZ EPJOH JO
UIFJS TQBSF UJNF
B
5FTU GPS WPXFMIPPE
C
3FUVSO UIF WPXFMT PG B TUSJOH
D
$PVOU UIF OVNCFS PG FMFNFOUT SFUVSOFE
$)"15&3 4*(/"-*/( "%7&34*5:
newtype Word' =
Word' String
deriving (Eq, Show)
vowels = "aeiou"
-- >>> 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:
.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
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
data BinaryTree a =
Leaf
| Node (BinaryTree a) a (BinaryTree a)
deriving (Eq, Ord, Show)
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))
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 :: * -> * -> *
(->) :: * -> * -> *
Int :: *
Char :: *
String :: *
[Char] :: *
#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
/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
$ 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
$ stack setup
$ 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
TUBDL FYFD
8IFO ZPV SBO build FBSMJFS
ZPV NBZ IBWF TFFO TPNFUIJOH
MJLF
Linking .stack-work/dist/{...noise...}/hello
$ hello
zsh: command not found: hello
$ stack exec -- hello
hello world
$)"15&3 #6*-%*/( 130+&$54
executable hello
-- [1]
hs-source-dirs: src
-- [2]
main-is: Main.hs
-- [3]
default-language: Haskell2010
-- [4]
build-depends: base >= 4.7 && < 5
-- [5]
library
hs-source-dirs: src
exposed-modules: Hello
build-depends: base >= 4.7 && < 5
default-language: Haskell2010
sayHello :: IO ()
sayHello = do
putStrLn "hello world"
import Hello
main :: IO ()
main = do
sayHello
$ stack build
$ stack exec hello
hello world
$ 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
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
sayHello :: IO ()
sayHello = do
putStrLn "hello world"
module Hello
()
where
sayHello :: IO ()
sayHello = do
putStrLn "hello world"
module Hello
( sayHello )
where
sayHello :: IO ()
sayHello = do
putStrLn "hello world"
&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
import DogsRule
import Hello
main :: IO ()
main = do
sayHello
dogs
library
hs-source-dirs: src
exposed-modules: DogsRule
, Hello
build-depends: base >= 4.7 && < 5
default-language: Haskell2010
otherwise :: Bool
(||) :: Bool -> Bool -> Bool
Prelude> :t bool
bool :: a -> a -> Bool -> a
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’
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
<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
<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
'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
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
-- src/Main.hs
main :: IO ()
main = do
name <- getLine
sayHello name
dogs
main :: IO ()
main = do
-- [1]
name <- getLine
-- [4] [3] [2]
sayHello name
-- [5]
dogs
-- [6]
$)"15&3 #6*-%*/( 130+&$54
$ stack build
"ǒ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
main :: IO ()
main = sayHello getLine
$ 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
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
import DogsRule
import Hello
import System.IO
main :: IO ()
main = do
hSetBuffering stdout NoBuffering
putStr "Please input your name: "
name <- getLine
sayHello name
dogs
: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
main = do
-- [1]
x1 <- getLine
-- [2] [3] [4]
x2 <- getLine
-- [5]
return (x1 ++ x2)
-- [6] [7]
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
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')
main :: IO ()
main = do c <- getChar
c' <- getChar
if c == c'
then putStrLn "True"
else return ()
$)"15&3 #6*-%*/( 130+&$54
ƶSF VQ UIF 4UBDL 8FƊMM VTF 4UBDLƊT new DPNNBOE UP DSFBUF UIJT
QSPKFDU
: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
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
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
5IJT XJMM XPSL GPS BOZ UZQF XIJDI IBT B Foldable JOTUBODF
In the expression:
all :: (a -> Bool) -> (b -> a) -> Bool
Prelude> :t intersperse
intersperse :: a -> [a] -> [a]
allWords :: IO WordList
allWords = do
dict <- readFile "data/dict.txt"
return (lines dict)
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
gameWords :: IO WordList
gameWords = do
aw <- allWords
return (filter gameLength aw)
where gameLength w =
let l = length (w :: String)
in l > minWordLength && l < maxWordLength
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
randomWord' :: IO String
randomWord' = gameWords >>= randomWord
(P GPS JU
Prelude> :t elem
elem :: Eq a => a -> [a] -> Bool
Prelude> elem 'a' "julie"
False
Prelude> elem 3 [1..5]
True
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
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
"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
/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
main :: IO ()
main = do
word <- randomWord'
let puzzle = freshPuzzle (fmap toLower word)
runGame puzzle
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
Ƒ JG ZPVS UI HVFTT TVQQMJFT UIF MBTU MFUUFS JO UIF XPSE
JU NBZ
TUJMM UFMM ZPV ZPV MPTU
.PEJGZJOH DPEF
$JQIFST 0QFO ZPVS $JQIFST NPEVMF BOE NPEJGZ JU TP UIBU
UIF $BFTBS BOE 7JHFO¨SF DJQIFST XPSL XJUI VTFS JOQVU
import Control.Monad
palindrome :: IO ()
palindrome = forever $ do
line1 <- getLine
case (line1 == reverse line1) of
True -> putStrLn "It's a palindrome!"
False -> putStrLn "Nope!"
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
gimmePerson :: IO ()
gimmePerson = undefined
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
$BCBM '"2
https://www.haskell.org/cabal/FAQ.html
5FTUJOH
$)"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
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
-- 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
-- Addition.hs
module Addition where
sayHello :: IO ()
sayHello = putStrLn "hello!"
$ 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
$ stack ghci
*G ZPV HPU IFSF
ZPVƊWF HPU B XPSLJOH UFTU CFE GPS NBLJOH B
TJNQMF UFTU DBTF JO )TQFD
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
sayHello :: IO ()
sayHello = putStrLn "hello!"
import Test.Hspec
Prelude> :r
[1 of 1] Compiling Addition
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 ...}
import Test.Hspec
main :: IO ()
main = hspec $ do
describe "Addition" $ do
it "1 + 1 is greater than 1" $ do
(1 + 1) > 1 `shouldBe` True
Prelude> main
Addition
1 + 1 is greater than 1
-- contrast with
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
Prelude> main
Addition
1 + 1 is greater than 1
2 + 2 is equal to 4
'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*/(
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)
*Addition> main
$)"15&3 5&45*/(
Addition
15 divided by 3 is 5
22 divided by 5 is 4 remainder 2
Prelude> main
Addition
1 + 1 is greater than 1
2 + 2 is equal to 4
x + 1 is always greater than x
"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
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
0.0
0.13712502861905426
2.9801894108743605
-8.960645064542609
4.494161946149201
7.903662448338119
-5.221729489254451
31.64874305324701
77.43118278366954
-539.7148886375935
26.87468214215407
/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*/(
5SZ MPBEJOH UIBU WJB ZPVS Addition NPEVMF BOE BTLJOH GPS B
sample TFU PG SBOEPN oneThroughThree WBMVFT
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*/(
: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*/(
: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*/(
-- equal probability
genMaybe :: Arbitrary a => Gen (Maybe a)
genMaybe = do
a <- arbitrary
elements [Nothing, Just 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*/(
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.
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
import Distribution.Simple
main = defaultMain
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
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
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
, ('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', "-----")
]
-- src/Main.hs
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
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
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
.... ..
*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
allowedChars :: [Char]
allowedChars = M.keys letterToMorse
allowedMorse :: [Morse]
allowedMorse = M.elems letterToMorse
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
*Main> main
+++ OK, passed 100 tests.
import Test.QuickCheck
data Trivial =
Trivial
deriving (Eq, Show)
main :: IO ()
main = do
sample trivialGen
Trivial
Trivial
Trivial
Trivial
Trivial
Trivial
Trivial
Trivial
*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)
Identity 5
Identity 3
Identity (-1)
Identity 12
Identity 16
Identity 0
"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*/(
instance (Arbitrary a,
Arbitrary b) =>
Arbitrary (Pair a b) where
arbitrary = pairGen
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"
data Sum a b =
First a
| Second b
deriving (Eq, Show)
First 'P'
First '\227'
First '\238'
First '.'
Second (-3)
First '\132'
Second (-12)
Second (-12)
First '\186'
Second (-11)
First '\v'
sumGenFirstPls :: (Arbitrary a,
Arbitrary b) =>
Gen (Sum a b)
sumGenFirstPls = do
a <- arbitrary
b <- arbitrary
frequency [(10, return $ First a),
(1, return $ Second b)]
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'
$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
import GHC.Generics
import Test.QuickCheck
data Bool' =
True'
| False'
deriving (Generic)
import Test.QuickCheck
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
plusAssociative x y z =
x + (y + z) == (x + y) + z
plusCommutative x y =
x + y == y + x
-- quot rem
(quot x y)*y + (rem x y) == x
*T ?
BTTPDJBUJWF *T JU DPNNVUBUJWF 6TF 2VJDL$IFDL UP
TFF JG UIF DPNQVUFS DBO DPOUSBEJDU TVDI BO BTTFSUJPO
reverse . reverse == id
f $ a = f a
f . g = \x -> f (g x)
$)"15&3 5&45*/(
'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
'BJMVSF
-- for a function
square x = x * x
-- why does this property not hold? Examine the type of sqrt.
squareIdentity = square . sqrt
*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*/(
data Fool =
Fulse
| Frue
deriving (Eq, Show)
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*/(
BOE
$)"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
.POPJE 4FNJHSPVQ
"MBO 1FSMJT
$)"15&3 .0/0*%
4&.*(3061
Ƒ "MHFCSBT
Ƒ -BXT
Ƒ .POPJET
Ƒ 4FNJHSPVQT
$)"15&3 .0/0*%
4&.*(3061
.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
mappend x mempty = x
mappend mempty x = x
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
-JTU
0OF PG UIF NPSF QFSWBTJWF UZQFT XJUI BO JOTUBODF PG Monoid JT
List $IFDL PVU IPX NPOPJEBM PQFSBUJPOT XPSL XJUI MJTUT
[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"
Prelude> mappend 1 1
<interactive>:7:1:
No instance for (Num a0) arising from a use of ‘it’
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
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
Prelude> Sum "Frank" <> Sum " " <> Sum "Herbert"
0S ZPV DPVME BMTP QVU ZPVS SumT JO B MJTU BOE VTF mconcat
$)"15&3 .0/0*%
4&.*(3061
-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
-- left identity
mappend mempty x = x
-- right identity
mappend x mempty = x
-- associativity
mappend x (mappend y z) = mappend (mappend x y) z
-- left identity
Prelude> mappend mempty (Sum 1)
Sum {getSum = 1}
-- right identity
Prelude> mappend (Sum 1) mempty
Sum {getSum = 1}
Prelude> :t (<>)
(<>) :: Monoid m => m -> m -> m
-- associativity
Prelude> (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]
data Booly a =
False'
| True'
deriving (Eq, Show)
data Optional a =
Nada
| Only a
deriving (Eq, Show)
&YQFDUFE PVUQVU
"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
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
*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
5IJT JT UIF PUIFS MBX GPS .POPJE UIF CJOBSZ PQFSBUJPO NVTU
CF BTTPDJBUJWF BOE JU NVTU IBWF B TFOTJCMF JEFOUJUZ WBMVF
newtype Listy a =
Listy [a]
deriving (Eq, Show)
$)"15&3 .0/0*%
4&.*(3061
import Data.Monoid
import Listy
$ tree
.
├── Listy.hs
└── ListyInstances.hs
/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
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
: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
.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
import Data.Monoid
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."
madlibbinBetter' :: Exclamation
-> Adverb
-> Noun
-> Adjective
-> String
madlibbinBetter' e adv noun adj = undefined
1 + (2 + 3) == (1 + 2) + 3
4 * (5 * 6) == (4 * 5) * 6
\ a b c -> a + (b + c) == (a + b) + c
\ a b c -> a * (b * c) == (a * b) * c
\ 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
import Data.Monoid
import Test.QuickCheck
-- for brevity
Prelude> type S = String
Prelude> type B = Bool
()
()
()
import Control.Monad
import Data.Monoid
import Test.QuickCheck
data Bull =
Fools
| Twoo
deriving (Eq, Show)
$)"15&3 .0/0*%
4&.*(3061
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
-- identity laws
mappend mempty x = x
mappend x mempty = x
newtype First' a =
First' { getFirst' :: Optional a }
deriving (Eq, Show)
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)
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
/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
-- Prefix, works.
data P =
Prefix Int String
-- Infix, works.
data Q =
Int :!!: String
data R =
:!!: Int String
data S =
Int Prefix String
newtype NonEmpty a =
NonEmpty (a, [a])
deriving (Eq, Ord, Show)
#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
id :: a -> a
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
main :: IO ()
main =
quickCheck (semigroupAssoc :: TrivialAssoc)
newtype BoolConj =
BoolConj Bool
newtype BoolDisj =
BoolDisj Bool
data Or a b =
Fst a
| Snd b
newtype Combine a b =
Combine { unCombine :: (a -> b) }
data Validation a b =
Failure a | Success b
deriving (Eq, Show)
newtype AccumulateRight a b =
AccumulateRight (Validation a b)
deriving (Eq, Show)
newtype AccumulateBoth a b =
AccumulateBoth (Validation a b)
deriving (Eq, Show)
.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
main :: IO ()
main = do
quickCheck (semigroupAssoc :: TrivialAssoc)
quickCheck (monoidLeftIdentity :: Trivial -> Bool)
quickCheck (monoidRightIdentity :: Trivial -> Bool)
newtype BoolConj =
BoolConj Bool
BoolConj True
Prelude> mempty `mappend` (BoolConj False)
BoolConj False
newtype BoolDisj =
BoolDisj Bool
newtype Combine a b =
Combine { unCombine :: (a -> b) }
newtype Comp a =
Comp (a -> a)
newtype Mem s a =
Mem {
runMem :: s -> (a,s)
}
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
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
'VODUPS
.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
--with a tuple!
Prelude> fmap (10/) (4, 5)
(4,2.0)
--with Either!
Prelude> fmap (++ ", Esq.") (Right "Chris Allen")
Right "Chris Allen, Esq."
-- 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
Prelude> :k (->)
(->) :: * -> * -> *
&YFSDJTFT #F ,JOE
(JWFO B UZQF TJHOBUVSF
EFUFSNJOF UIF LJOET PG FBDI UZQF WBSJ
BCMF
a -> a
a -> b a -> T (b a)
c a b -> c b a
-- functors1.hs
data FixMePls =
FixMe
| Pls
deriving (Eq, Show)
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.
-- Functor is:
fmap :: Functor f => (a -> b) -> f a -> f b
/PUJDF TPNFUIJOH
-- functors2.hs
data FixMePls a =
FixMe
| Pls a
deriving (Eq, Show)
Prelude> :l code/functors2.hs
[1 of 1] Compiling Main
Ok, modules loaded: Main.
-- functors3.hs
data FixMePls a =
FixMe
| Pls a
deriving (Eq, Show)
-FUƊT TFF IPX PVS JOTUBODF MJOFT VQ XJUI UIF UZQF PG fmap
Prelude> :l code/functors3.hs
[1 of 1] Compiling Main
Ok, modules loaded: Main.
$)"15&3 '6/$503
-- functors4.hs
data FixMePls a =
FixMe
| Pls a
deriving (Eq, Show)
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.
*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
*EFOUJUZ
5IF ƶSTU MBX JT UIF MBX PG JEFOUJUZ
fmap id == id
$PNQPTJUJPO
5IF TFDPOE MBX GPS 'VODUPS JT UIF MBX PG DPNQPTJUJPO
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
data WhoCares a =
ItDoesnt
| Matter a
| WhatThisIsCalled
deriving (Eq, Show)
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
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
data CountingBad a =
Heisenberg Int a
deriving (Eq, Show)
Prelude> fmap (++ " Jesse") . fmap (++ " lol") $ oneWhoKnocks
Heisenberg 2 "Uncle lol Jesse"
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
Prelude> :t const
const :: a -> b -> a
Prelude> let replaceWithP = const 'p'
8FƊMM VTF JU XJUI fmap OPX GPS WBSJPVT EBUBUZQFT UIBU IBWF
JOTUBODFT
-- data [] a = [] | a : [a]
"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
/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
-FUƊT SFWJFX XIBU XF KVTU TBX
CVU XJUI BO 9SBZ UVSOFE PO
$)"15&3 '6/$503
-- In:
replaceWithP lms
-- So applying
replaceWithP
-- to
lms
-- accomplishes
List (Maybe String) -> Char
$)"15&3 '6/$503
-- In:
fmap replaceWithP lms
-- So applying
fmap replaceWithP
-- to
lms
$)"15&3 '6/$503
-- accomplishes:
List (Maybe String) -> List Char
-- In:
(fmap . fmap) replaceWithP lms
-- 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
-- In
(fmap . fmap . fmap) replaceWithP lms
-- So applying
(fmap . fmap . fmap) replaceWithP
-- to
lms
$)"15&3 '6/$503
-- accomplishes
List (Maybe String) -> List (Maybe String)
8F TBX UIF QBUUFSO BCPWF
CVU GPS DMBSJUZ XFƊSF HPJOH UP TVN
NBSJ[F IFSF CFGPSF XF NPWF PO
8FƊMM XPSL UISPVHI UIF TBNF JEFB
CVU XJUI NPSF GVOLZ TUSVD
UVSF UP MJǒ PWFS
5ISJDF
$)"15&3 '6/$503
main :: IO ()
main = do
putStr "replaceWithP' lms: "
print (replaceWithP' 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
&YQFDUFE SFTVMU
Prelude> a
[2]
Prelude> b
Just ["Hi,lol","Hellolol"]
Prelude> c 1
-2
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
data Two a b =
Two a b
deriving (Eq, Show)
data Or a b =
First a
| Second b
deriving (Eq, Show)
Prelude> :k Either
Either :: * -> * -> *
Prelude> :k Either Integer
Either Integer :: * -> *
Prelude> :k Either Integer String
Either Integer String :: *
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
fmap id = id
fmap (p . q) = (fmap p) . (fmap q)
Prelude> quickCheck li
+++ OK, passed 100 tests.
(SPPWZ
$)"15&3 '6/$503
import Test.QuickCheck
import Test.QuickCheck.Function
$BO ZPV JNQMFNFOU POF GPS UIJT UZQF 8IZ 8IZ OPU
.BZCF
-FUƊT TUBSU XJUI TPNF PSEJOBSZ QBUUFSO NBUDIJOH PO .BZCF
XF DBO RVFSZ UIF UZQF PG UIF FYQSFTTJPOT JO ()$J BOE TFF GPS
PVSTFMWFT UIF NPSF HFOFSJD UZQF
&YFSDJTF 1PTTJCMZ
data Possibly a =
LolNope
| Yeppers a
deriving (Eq, Show)
&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
-- f ~ Either e
5BLF B GFX NPNFOUT UP QMBZ BSPVOE XJUI UIJT BOE OPUF IPX
JU XPSLT
4IPSU &YFSDJTF
data Sum a b =
First a
| Second b
deriving (Eq, Show)
:PVS IJOU GPS UIJT POF JT UIBU ZPVƊSF XSJUJOH UIF GPMMPXJOH
GVODUJPO
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
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}
-PPLT MJLF JEFOUJUZ SJHIU -FUƊT VTF UIJT JO UIF 3&1- BOE SVO
JU UISPVHI UIF 'VODUPS MBXT
$)"15&3 '6/$503
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
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"
*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
meTooIsm :: IO String
meTooIsm = do
input <- getLine
return (input ++ "and me too!")
bumpIt :: IO Int
bumpIt = do
intVal <- getInt
return (intVal + 1)
-- This'll work
maybeToList :: Nat Maybe []
maybeToList Nothing = []
maybeToList (Just a) = [a]
-- This'll work
maybeToList :: Nat Maybe [] a
maybeToList Nothing = []
maybeToList (Just a) = [a]
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
data Tuple a b =
Tuple a b
deriving (Eq, Show)
data Tuple a b =
Tuple a b
deriving (Eq, Show)
newtype Flip f a b =
Flip (f b a)
deriving (Eq, Show)
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
import GHC.Arr
data D =
D (Array Word Word) Int Int
data Sum a b =
First a
| Second b
data Company a b c =
DeepBlue a c
| Something b
data More a b =
L a b a
| R b a b
deriving (Eq, Show)
data Quant a b =
Finance
| Desk a
| Bloor b
data K a b =
K a
$)"15&3 '6/$503
newtype Flip f a b =
Flip (f b a)
deriving (Eq, Show)
newtype K a b =
K a
data EvilGoateeConst a b =
GoatyConst b
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)
data List a =
Nil
| Cons a (List a)
data GoatLord a =
NoGoat
| OneGoat a
| MoreGoats (GoatLord a) (GoatLord a) (GoatLord a)
:PVƊMM VTF BO FYUSB GVODUPS GPS UIJT POF
BMUIPVHI ZPVS TPMV
UJPO NJHIU EP JU NPOPNPSQIJDBMMZ XJUIPVU VTJOH GNBQ
$)"15&3 '6/$503
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
a :: *
f :: * -> *
Weird :: (* -> *) -> * -> *
5IBOLT UP "OESB[ #BKU GPS JOTQJSJOH UIJT FYFSDJTF
$)"15&3 '6/$503
f :: a -> b
-- ``more structure''
fmap f :: f a -> f b
-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
"QQMJDBUJWF
$)"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
Ƒ EP B MPU PG MJǒJOH
-- fmap
(<$>) :: Functor f => (a -> b) -> f a -> f b
f (a -> b)
-- and
f a
f f f
(a -> b) a b
mappend :: f f f
$ :: (a -> b) a b
-- List
[(*2), (*3)] <*> [4, 5]
[2 * 4, 2 * 5, 3 * 4, 3 * 5]
-- reduced
[8,10,12,15]
-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 ~ []
pure :: a -> f a
pure :: a -> [ ] a
[1,4,9]
f ~ []
[ 3 , 5 , 4 , 8 ]
-- [1] [2] [3] [4]
$)"15&3 "11-*$"5*7&
.PSF WJTVBMMZ
*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&
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"
import Control.Applicative
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
5SZ JU /PX USZ VTJOH fmap UP HFU UIF MFOHUI PG UIF SFTVMUJOH
TUSJOH PG UIF ƶSTU FYBNQMF
&YFSDJTFT -PPLVQT
QVSF
(<$>)
-- or fmap
(<*>)
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]
x :: Maybe Int
x = elemIndex 3 [1, 2, 3, 4, 5]
y :: Maybe Int
y = elemIndex 4 [1, 2, 3, 4, 5]
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
*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
)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
)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
$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&
-- f ~ Constant e
pure :: a -> f a
pure :: a -> Constant e a
newtype Constant a b =
Constant { getConstant :: a }
deriving (Eq, Ord, Show)
.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&
)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
data Person =
Person Name Address
deriving (Eq, Show)
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
In the expression:
fmap (fmap Person (mkName "Babe")) maybeAddy
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
newtype Name =
Name String deriving (Eq, Show)
newtype Address =
Address String deriving (Eq, Show)
if 4 > 25
then Nothing
else Just "babe"
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&
f :: Person
a :: Name "babe"
fmap f (Just a) =
Just (f a)
Maybe (Address -> Person) -> Maybe Address -> Maybe Person
f ( a -> b ) -> f a -> f b
#FGPSF XF NPPPPWF PO
import Control.Applicative
Prelude> :t cow1
cow1 :: Maybe (Int -> Int -> Cow)
Prelude> :t cow2
cow2 :: Maybe (Int -> Cow)
Prelude> :t cow3
cow3 :: Maybe Cow
$)"15&3 "11-*$"5*7&
Prelude> :t cow1
cow1 :: Applicative f => f String -> f Int -> f Int -> f Cow
Prelude> :t cow2
cow2 :: Maybe Int -> Maybe Int -> Maybe Cow
Prelude> :t cow3
cow3 :: Maybe Int -> Maybe Cow
Prelude> :t cow4
cow4 :: Maybe Cow
-- f ~ Maybe
cow1 :: Maybe (Int -> Int -> Cow)
cow1 = fmap Cow (noEmpty "Bess")
f ~ Maybe
Prelude> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
*G ZPV NBLF BOZ NJTUBLFT UIF 3&1- XJMM MFU ZPV LOPX
In the expression:
(<*>) :: Maybe (a -> b) -> Maybe a -> f b
(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
*EFOUJUZ
)FSF JT UIF EFƶOJUJPO PG UIF JEFOUJUZ MBX
pure id <*> v = v
"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]
$PNQPTJUJPO
)FSF JT UIF EFƶOJUJPO PG UIF DPNQPTJUJPO MBX GPS BQQMJDB
UJWFT
: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 (.) <*> Just (+1) <*> Just (*2) <*> Just 1
)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 ((+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
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
*OUFSDIBOHF
8F CFHJO BHBJO CZ MPPLJOH BU UIF EFƶOJUJPO PG UIF JOUFS
DIBOHF MBX
(<*>) :: Applicative f
=> f (x -> y)
-> f x
-> f y
$)"15&3 "11-*$"5*7&
f ~ Maybe
x ~ (a -> b)
y ~ b
(x -> y) ~ (a -> b) -> b
"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
import Data.Monoid
import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes
data Bull =
Fools
| Twoo
deriving (Eq, Show)
main :: IO ()
main = quickBatch (monoid Twoo)
$)"15&3 "11-*$"5*7&
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
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.
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&
-- changes to
[1, 2, 3] ++ [4, 5, 6]
[1, 2, 3, 4, 5, 6]
-- changes to
[
1 <> 4
, 2 <> 5
, 3 <> 6
]
import Control.Applicative
import Data.Monoid
import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes
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
-- Identity
n * 1 == n
:PVƊMM ƶOE PVU XIBU UIF ƌQVSFƍ EPFT IFSF XIFO ZPV XSJUF
UIF "QQMJDBUJWF GPS ;JQ-JTU ZPVSTFMG
data List a =
Nil
| Cons a (List a)
deriving (Eq, Show)
&YQFDUFE SFTVMU
*O DBTF ZPV HFU TUVDL VTF UIF GPMMPXJOH GVODUJPOT BOE IJOUT
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&
data List a =
Nil
| Cons a (List a)
deriving (Eq, Show)
newtype ZipList' a =
ZipList' (List a)
deriving (Eq, Show)
/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&
repeat 1 == repeat 1
-- f ~ Either e
pure :: a -> f a
pure :: a -> Either e a
$)"15&3 "11-*$"5*7&
eitherToValid . validToEither == id
validToEither . eitherToValid == id
data Errors =
DividedByZero
| StackOverflow
| MooglesChewedWires
deriving (Eq, Show)
success == Success 2
failures =
Failure [MooglesChewedWires]
<*> Failure [StackOverflow]
failures ==
Failure [MooglesChewedWires
, StackOverflow]
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
-- 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
$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
stops :: String
stops = "pbtdkg"
vowels :: String
vowels = "aeiou"
%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
.POBE
5IFSF JT OPUIJOH TP
QSBDUJDBM BT B HPPE UIFPSZ
$)"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
"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/"%
$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
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
#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/"%
-- compare
"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
"TJEF GSPN UIF OVNCFSJOH UIFTF BQQFBS UIF TBNF -FUƊT USZ
UIFN PVU
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
Prelude> :t zipWith3
zipWith3 :: (a -> b -> c -> d) ->
[a] -> [b] -> [c] -> [d]
'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
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
8FMM
MFUƊT TUBSU XJUI UIF UZQFT 5IF UZQF PG XIBU ZPV KVTU
USJFE UP EP JT UIJT
getLine :: IO String
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/"%
-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
-- same as pure
return :: Monad m => a -> m a
return :: a -> [ ] a
return :: a -> [a]
-FUƊT TUBSU XJUI B GVODUJPO BOE JEFOUJGZ IPX UIF QBSUT ƶU XJUI
PVS NPOBEJD UZQFT
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
"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
-- m ~ Maybe
-- same as pure
return :: Monad m => a -> m a
return :: a -> Maybe a
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
'JSTU
XFƊMM DMFBO JU VQ XJUI Monad
UIFO XFƊMM TFF XIZ XF DBOƊU
EP UIJT XJUI Applicative
$)"15&3 .0/"%
doSomething = do
a <- f
b <- g
c <- h
pure (a, b, c)
doSomething' n = do
a <- f n
b <- g a
c <- h b
pure (a, b, c)
doSomething' n = do
a <- f n
b <- g a
c <- h b
pure (a, b, c)
(Just x) >>= k = k x
Nothing >>= _ = Nothing
(Just x) >>= k = k x
Nothing >>= _ = Nothing
\ "Bess" ->
noNegative 5 >>=
\ agey ->
noNegative 499 >>=
\ weighty ->
weightCheck (Cow nammy agey weighty)
"OE IPX EP UIF HVUT GBMM XIFO XF FYQMPEF UIJT QPPS CPWJOF
$)"15&3 .0/"%
(Just x) >>= k = k x
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
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/"%
-- 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
-- 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)
Prelude> mkSoftware 0 0
$)"15&3 .0/"%
(<*>) == ap
-- Keeping in mind
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
ap :: Monad m => m (a -> b) -> m a -> m b
data Sum a b =
First a
| Second b
deriving (Eq, Show)
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
return :: a -> m a
m >>= return = m
-- [1] [2] [3]
$)"15&3 .0/"%
return x >>= f = f x
-- [1] [2] [3]
"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
#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
monad laws:
left identity: +++ OK, passed 500 tests.
right identity: +++ OK, passed 500 tests.
associativity: +++ OK, passed 500 tests.
import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes
data CountMe a =
CountMe Integer a
deriving (Eq, Show)
CountMe n a >>= f =
let CountMe _ b = f a
in CountMe (n + 1) b
$)"15&3 .0/"%
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
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
CountMe _ a >>= f = f a
CountMe n a >>= f =
let CountMe n' b = f a
in CountMe (n + n') b
fmap id = id
-- guarantees
import Control.Monad
askForAge :: IO Int
askForAge = getAge "Hello! How old are you? "
data Nope a =
NopeDotJpg
data PhhhbbtttEither b a =
Left a
| Right b
data List a =
Nil
| Cons a (List a)
%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
let x = 2 in x + 2
"QQMZJOH TUSVDUVSF
+BDL 1SFMVUTLZ
$)"15&3 .0/"%4 (0/& 8*-%
.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*-%
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
}
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
'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
getCurrentTime :: IO UTCTime
)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
textUuid :: IO Text
textUuid =
fmap (T.pack . UUID.toString) UUIDv4.nextRandom
nextRandom :: IO UUID
"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*-%
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
: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
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*-%
"OE XFƊMM NBLF TPNF USJWJBM GVODUJPOT BHBJO GPS UIF QVSQPTFT
PG EFNPOTUSBUJPO
$)"15&3 .0/"%4 (0/& 8*-%
Prelude> (f <||> g) 0
$)"15&3 .0/"%4 (0/& 8*-%
False
Prelude> (f <||> g) 9001
True
.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
import Network.Socket
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)
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
$ 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
alphaNum :: String
alphaNum = ['A'..'Z'] ++ ['0'..'9']
shortyGen :: IO [Char]
shortyGen = replicateM 7 (randomElement alphaNum)
saveURI :: R.Connection
-> BC.ByteString
-> BC.ByteString
-> IO (Either R.Reply R.Status)
saveURI conn shortURI uri =
R.runRedis conn $ R.set shortURI uri
getURI :: R.Connection
-> BC.ByteString
-> IO (Either R.Reply (Maybe BC.ByteString))
getURI conn shortURI = R.runRedis conn $ R.get shortURI
app :: R.Connection
-> ScottyM ()
app rConn = do
-- [1]
get "/" $ do
-- [2]
uri <- param "uri"
-- [3]
*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*-%
B
63- QBUI DBQUVSF
get "/user/:name/view" $ do
<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
http://localhost:3000/?name=Blah&state=Texas
$)"15&3 .0/"%4 (0/& 8*-%
$POWFSUJOH UIF TIPSU DPEF GPS UIF 63* JOUP B $IBS CZUFTUSJOH
GPS TUPSBHF JO 3FEJT
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]
)BQQZ QBUI
main :: IO ()
main = do
rConn <- R.connect R.defaultConnectInfo
scotty 3000 (app rConn)
&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*-%
'PMEBCMF
,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
*O TPNF DBTFT
UIF DPNQJMFS DBO JEFOUJGZ BOE VTF UIF TUBO
EBSE .POPJE GPS B UZQF
XJUIPVU VT CFJOH FYQMJDJU
"hello julie"
*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
Sum {getSum = 0}
Prelude> foldMap (*5) Nothing :: Product Integer
Product {getProduct = 1}
*EFOUJUZ
8FƊMM LJDL UIJOHT PƵ CZ XSJUJOH B 'PMEBCMF JOTUBODF GPS *EFOUJUZ
data Identity a =
Identity a
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
.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
foldl _ z Nada = z
foldl f z (Yep x) = f z x
/PUF UIBU JG ZPV EPOƊU UFMM JU XIBU .POPJE ZPV NFBO
JUƊMM
XIJOHF BCPVU UIF UZQF CFJOH BNCJHVPVT
[1,1,1]
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
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
5IJT BOE UIF OFYU POF BSF OJDFS XJUI foldMap
CVU foldr JT
ƶOF UPP
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
5SBWFSTBCMF
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"#-&
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"#-&
5P UIFTF
USBWFSTF
-FUƊT MPPL OFYU BU UIF UZQF PG traverse
traverse
:: (Applicative f, Traversable t) =>
(a -> f b) -> t a -> f (t b)
-- contrast with
-- contrast with
Prelude> :t traverse f xs
traverse f xs :: Maybe [b]
Nothing
Prelude> morseToChar "-.-."
Just 'c'
Prelude> :t sequence
sequence :: Monad m => [m a] -> m [a]
-- we want this
(sequence .) . fmap = \ f xs -> sequence (fmap f xs)
-- not this
sequence . fmap = \ f -> sequence (fmap f)
-- 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
pipelineFn :: Query
-> IO (Either Err [(SomeObj, IoOnlyObj)])
pipelineFn query = do
a <- fetchFn query
traverse makeIoOnlyObj (mapM decodeFn a)
pipelineFn :: Query
-> IO (Either Err [(SomeObj, IoOnlyObj)])
pipelineFn =
(traverse makeIoOnlyObj . mapM decodeFn =<<) . fetchFn
pipelineFn :: Query
-> IO (Either Err [(SomeObj, IoOnlyObj)])
pipelineFn = (traverse makeIoOnlyObj
. traverse decodeFn =<<) . fetchFn
-- from `transformers`
Prelude> import Data.Functor.Constant
&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)
foldr _ z (Left _) = z
foldr f z (Right y) = f y z
(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
/BUVSBMJUZ
t . traverse f = traverse (t . f)
*EFOUJUZ
$PNQPTJUJPO
/BUVSBMJUZ
*EFOUJUZ
$PNQPTJUJPO
type TI = []
main = do
let trigger = undefined :: TI (Int, Int, [Int])
quickBatch (traversable trigger)
*EFOUJUZ
$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
data Tree a =
Empty
| Leaf a
| Node (Tree a) a (Tree a)
deriving (Eq, Show)
)JOUT
3FBEFS
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
import Control.Applicative
boop = (*2)
doop = (+10)
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
Prelude> bbop 3
19
4P XIBUƊT IBQQFOJOH
$)"15&3 '6/$5*0/4 8"*5*/( '03 */165
-- f . g = \ x -> f (g 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
((+) . (*2)) 5 3
(\ x -> (+) (2 * x)) 5 3
(\ 5 -> (+) (2 * 5)) 3
((+) 10) 3
Prelude> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(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
import Data.Char
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
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)
((->) r)
-- is
r ->
-- f is ((->) a)
newtype Reader r a =
Reader { runReader :: r -> a }
-- 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)
&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 ???
-- Applicative f =>
-- f ~ (->) r
pure :: a -> f a
pure :: a -> (r -> a)
newtype HumanName =
HumanName String
deriving (Eq, Show)
newtype DogName =
DogName String
deriving (Eq, Show)
newtype Address =
Address String
deriving (Eq, Show)
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
-- without Reader
getDog :: Person -> Dog
getDog p =
Dog (dogName p) (address p)
-- with Reader
getDogR :: Person -> Dog
getDogR =
Dog <$> dogName <*> address
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
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
fooBind m k = \r -> k (m r) r
fooBind :: (t2 -> t1) -> (t1 -> t2 -> t) -> t2 -> t
TUSVDUVSF
$)"15&3 '6/$5*0/4 8"*5*/( '03 */165
: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
(>>=) :: Reader r a
-> (a -> Reader r b)
-> Reader r b
(Reader ra) >>= aRb =
Reader $ \r -> ???
f <*> a = \r -> f r (a r)
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
QPTTJCMZ NBOZ
WBMVFT UIBU ZPVƊSF HFUUJOH PVU PG UIF 3FBEFS
import Control.Applicative
import Data.Maybe
x = [1, 2, 3]
y = [4, 5, 6]
z = [7, 8, 9]
*ReaderPractice> x1
Just (6,9)
*ReaderPractice> x2
Nothing
*ReaderPractice> x3 3
(Just 9,Just 9)
*ReaderPractice> fromMaybe 0 xs
6
*ReaderPractice> fromMaybe 0 zs
0
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]
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
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
4UBUF
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
: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> :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)
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 }
/PUF UIBU random TIPVME MPPL BO BXGVM MPU MJLF 4UBUF UP ZPV
IFSF
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&
/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&
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]
,FFQ PO SPMMJOH
*O UIF GPMMPXJOH FYBNQMF
XF LFFQ SPMMJOH B TJOHMF EJF VOUJM XF
SFBDI PS FYDFFE B TVN PG
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
newtype Moi s a =
Moi { runMoi :: s -> (a, s) }
4UBUF 'VODUPS
*NQMFNFOU UIF 'VODUPS JOTUBODF GPS 4UBUF
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&
4UBUF .POBE
8SJUF UIF .POBE JOTUBODF GPS 4UBUF
(>>=) :: Moi s a
-> (a -> Moi s b)
-> Moi s b
(Moi f) >>= g =
???
$)"15&3 45"5&
main :: IO ()
main =
mapM_ (putStrLn . fizzBuzz) [1..100]
http://c2.com/cgi/wiki?FizzBuzzTest
$)"15&3 45"5&
import Control.Monad
import Control.Monad.Trans.State
main :: IO ()
main =
mapM_ putStrLn $ reverse $ fizzbuzzList [1..100]
import Control.Monad
import Control.Monad.Trans.State
-- http://hackage.haskell.org/package/dlist
import qualified Data.DList as DL
main :: IO ()
main =
mapM_ putStrLn $ fizzbuzzList [1..100]
Prelude> :t mapM_
mapM_ :: (Monad m, Foldable t) => (a -> m b) -> t a -> m ()
main :: IO ()
main =
mapM_ putStrLn $ fizzbuzzList [1..100]
'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
get :: State s s
get = ???
&YQFDUFE PVUQVU
3VO UIF 4UBUF XJUI Ԣ BOE HFU UIF TUBUF UIBU SFTVMUT
3VO UIF 4UBUF XJUI Ԣ BOE HFU UIF WBMVF UIBU SFTVMUT
/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&
1BSTFS DPNCJOBUPST
8JUIJO B DPNQVUFS
OBUVSBM MBOHVBHF JT
VOOBUVSBM
"MBO 1FSMJT
$)"15&3 1"34&3 $0.#*/"5034
S(entence)
/ \
Boy plays (verb)
(subject) \
with (preposition)
\
dog (object)
import Text.Trifecta
stop :: Parser a
stop = unexpected "stop"
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
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
-- 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
-- from Text.ParserCombinators.HuttonMeijer
-- polyparse-1.11
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'
Prelude> main
TIBLFT ƶTU BU TLZ
$)"15&3 1"34&3 $0.#*/"5034
stop:
Failure (interactive):1:1: error: unexpected
stop
123<EOF>
^
one:
Success '1'
one':
Failure (interactive):1:2: error: unexpected
stop
123<EOF>
^
$)"15&3 1"34&3 $0.#*/"5034
oneTwo:
Success '2'
oneTwo':
Failure (interactive):1:3: error: unexpected
stop
123<EOF>
^
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
import Control.Applicative
import Data.Ratio ((%))
import Text.Trifecta
badFraction = "1/0"
alsoBad = "10"
shouldWork = "1/2"
shouldAlsoWork = "2/1"
5IFO UIF GBDU UIBU PVS ƶOBM SFTVMU JT B 3BUJPOBM NBLFT UIF
Integral a => a WBMVFT JOUP DPODSFUF *OUFHFS WBMVFT
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
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
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
main :: IO ()
main = do
print $ parseString parseFraction mempty badFraction
print $ parseString parseFraction mempty shouldWork
print $ parseString parseFraction mempty shouldAlsoWork
print $ parseString parseFraction mempty alsoBad
Prelude> main
Success *** Exception: Ratio has zero denominator
$)"15&3 1"34&3 $0.#*/"5034
testVirtuous :: IO ()
testVirtuous = do
print $ parseString virtuousFraction mempty badFraction
print $ parseString virtuousFraction mempty alsoBad
print $ parseString virtuousFraction mempty shouldWork
print $ parseString virtuousFraction mempty shouldAlsoWork
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)
^
Prelude> parseString (integer >> eof) mempty "123"
Success ()
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
-- Text.Parser.Combinators
class Alternative m => Parsing m where
try :: m a -> m a
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
eof :: m ()
-- > eof = notFollowedBy anyChar <?> "end of input"
-- 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
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
import Control.Applicative
import Text.Trifecta
type NumberOrString =
Either Integer String
a = "blah"
b = "123"
c = "123blah789"
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
-- | 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
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
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,
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"
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
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
main = do
print $ parseString parseNos mempty eitherOr
)PXFWFS
GPS PVS QVSQPTFT XF DBO KVTU TBZ UIBU UIF UZQF JT
TQFDJƶDBMMZ 5SJGFDUBƊT 1BSTFS UZQF
-- same deal
Prelude> :t MyName <$> someLetter
MyName <$> someLetter :: Parser MyName
Prelude> :t MyName `fmap` someLetter
MyName `fmap` someLetter :: Parser MyName
#SJMM
#BDL UP PVS PSJHJOBM DPEF
XIJDI XJMM BDUVBMMZ TQJU PVU BO
FSSPS
Prelude> main
Failure (interactive):1:1: error: expected: integer,
letter
Prelude> eitherOr
"\n123\nabc\n456\ndef\n"
eitherOr :: String
eitherOr = [r|123
abc
456
def
|]
eitherOr :: String
eitherOr = [r|
123
abc
456
def
|]
main = do
print $ parseString parseNos mempty eitherOr
Prelude> main
Success (Left 123)
eitherOr :: String
eitherOr = [r|
123
abc
456
def|]
; comment
[section]
host=wikipedia.org
alias=claw
https://en.wikipedia.org/wiki/INI_file
$)"15&3 1"34&3 $0.#*/"5034
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
headerEx :: ByteString
headerEx = "[blah]"
assignmentEx :: ByteString
assignmentEx = "woot=1"
5IFO XF QBSTF BOE UISPX BXBZ UIF ƌƍ VTFE UP TFQBSBUF LFZT
BOE WBMVFT
skipEOL -- important!
1JUZ $BOƊU QBSTF UIF TFDPOE BTTJHONFOU #VU UIF ƶSTU WFS
TJPO UIBU JODMVEFT UIF skipEOL TIPVME XPSL
commentEx :: ByteString
commentEx =
"; last modified 1 April\
\ 2001 by John Doe"
commentEx' :: ByteString
commentEx' =
"; blah\n; woot\n \n;hah"
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
|]
data Section =
Section Header Assignments
deriving (Eq, Show)
newtype Config =
Config (Map Header Assignments)
deriving (Eq, Show)
skipWhitespace :: Parser ()
skipWhitespace =
skipMany (char ' ' <|> char '\n')
rollup :: Section
-> Map Header Assignments
-> Map Header Assignments
rollup (Section h a) m =
M.insert h a m
"ǒFS ZPV MPBE UIJT DPEF JOUP ZPVS 3&1- USZ SVOOJOH
main :: IO ()
main = hspec $ do
Prelude> let tknBoth = token (char 'a') >> token (char 'b')
Prelude> parseString (some tknBoth) mempty "a b a b"
Success "bb"
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
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
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
parsecP :: (Show a)
=> Parsec String () a
-> String -> IO ()
parsecP = parseTest
attoP :: Show a
=> A.Parser a
-> ByteString -> IO ()
attoP p i =
print $ parseOnly p i
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
$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
/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
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
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"}
}
|]
<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
-- Into:
import Data.ByteString (ByteString)
$)"15&3 1"34&3 $0.#*/"5034
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
‘LBS.ByteString’ is defined in
‘Data.ByteString.Lazy.Internal’
In the first argument of ‘decodeStrict’,
namely ‘sectionJson’
In the expression: decodeStrict sectionJson
#BDL UP UIFƒ+40/
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
-- FromJSON
ByteString -> Value -> yourType
-- parse -> unmarshall
-- ToJSON
yourType -> Value -> ByteString
-- marshall -> serialize
data NumberOrString =
Numba Integer
| Stringy Text
deriving (Eq, Show)
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
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
eitherDec :: ByteString
-> Either String NumberOrString
eitherDec = eitherDecode
main = do
print $ dec "blah"
Prelude> main
Nothing
$)"15&3 1"34&3 $0.#*/"5034
main = do
print $ dec "blah"
print $ eitherDec "blah"
Prelude> main
Nothing
Left "Error in $: Failed reading:
not a valid json value"
-- Relevant to precedence/ordering,
-- cannot sort numbers like strings.
data NumberOrString =
NOSS String
| NOSI Integer
data SemVer =
SemVer Major Minor Patch Release Metadata
&YQFDUFE SFTVMUT
$)"15&3 1"34&3 $0.#*/"5034
&YQFDUFE SFTVMUT
data PhoneNumber =
PhoneNumber NumberingPlanArea Exchange LineNumber
deriving (Eq, Show)
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
import Data.Word
data IPAddress =
IPAddress Word32
deriving (Eq, Ord, Show)
import Data.Word
data IPAddress6 =
IPAddress6 Word64 Word64
deriving (Eq, Ord, Show)
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
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
$PNQPTJOH UZQFT
5 4 &MJPU
$)"15&3 & 1-63*#64 .0/"%
*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 }
Prelude> :t id
id :: a -> a
Prelude> :k Identity
Identity :: * -> *
$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)
(JWFO UIF BCPWF WBMVF
UIF UZQF WBSJBCMFT HFU CPVOE BDDPSE
JOHMZ
Compose { getCompose :: f (g a) }
f ~ []
g ~ Maybe
a ~ Int
newtype Compose f g a =
Compose { getCompose :: f (g a) }
deriving (Eq, Show)
Compose { getCompose :: f (g a) }
newtype One f a =
One (f a)
deriving (Eq, Show)
newtype Three f g h a =
Three (f (g (h a)))
deriving (Eq, Show)
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/"%
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
-- 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
(>>=) = ???
0S GPSNVMBUFE EJƵFSFOUMZ
"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
$PNQPTF 5SBWFSTBCMF
8SJUF UIF 5SBWFSTBCMF JOTUBODF GPS $PNQPTF
*UƊT B GVODUPS UIBU DBO NBQ PWFS UXP UZQF BSHVNFOUT JOTUFBE
PG KVTU POF 8SJUF #JGVODUPS JOTUBODFT GPS UIF GPMMPXJOH UZQFT
data Quadriceps a b c d =
Quadzzz a b c d
data Either a b =
Left a
| Right b
.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]
%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] }
*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
(Identity a) >>= f = f a
(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(a -> IdentityT m b)
(a -> IdentityT m b)
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
Prelude> :t IdentityT
IdentityT :: f a -> IdentityT f a
Prelude> :t runIdentityT
runIdentityT :: IdentityT f a -> f a
(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
undefined
(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
let aimb = ma >>= f
in undefined
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
(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(a -> IdentityT m b)
-- over
m a
-- and got
m (IdentityT 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
(>>=) :: 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
(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
let aimb = join (fmap runIdentityT (fmap f ma))
in aimb
-- Remember:
IdentityT :: f a -> IdentityT f a
(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
let aimb = join (fmap runIdentityT (fmap f ma))
in IdentityT aimb
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
-- Functor law:
fmap (f . g) == fmap f . fmap g
(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
IdentityT $ ma >>= runIdentityT . f
$)"15&3 & 1-63*#64 .0/"%
5BLF B NPNFOU BOE XPSL PVU GPS ZPVSTFMG IPX UIBU JT GVOD
UJPOBMMZ FRVJWBMFOU UP PVS JNQMFNFOUBUJPO
(>>=) :: IdentityT m a
-> (a -> IdentityT m b)
-> IdentityT m b
(IdentityT ma) >>= f =
IdentityT $ ma >>= runIdentityT . f
$)"15&3 & 1-63*#64 .0/"%
-- Not this
(IdentityT ma) ...
-- Not this
... ma >>= ...
(Monad m) => m (m a)
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
let aimb :: m (m b)
aimb = fmap runIdentityT (fmap f ma)
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
.JDIFM 'PVDBVMU
$)"15&3 45"$, Ɖ&. 61
.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
newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a) }
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
5IF ԕԐԑ SFQSFTFOUT UIF GVODUJPO m (Maybe (a -> b)) BOE UIF
ԜԜԐ SFQSFTFOUT UIF m (Maybe a)
:PVƊMM HFU UIJT FSSPS JG ZPV USZ JU
-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
(>>=) :: 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
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
%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
f <*> a = undefined
v >>= f = 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 }
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
(>>=) :: 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]
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
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) }
newtype WriterT w m a =
WriterT { runWriterT :: m (a, w) }
newtype StateT s m a =
StateT { runStateT :: s -> m (a, s) }
newtype RWST r w s m a =
RWST { runRWST :: r -> s -> m (a, s, w) }
newtype StateT s m a =
StateT { runStateT :: s -> m (a,s) }
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
newtype MaybeT m a =
MaybeT { runMaybeT :: m (Maybe a) }
newtype ReaderT r m a =
ReaderT { runReaderT :: r -> m a }
import Control.Monad.Trans.Except
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Reader
-- 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)
&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
.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
: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
.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 )
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
import Web.Scotty
MJLF TP
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
import Control.Monad.Trans.Class
*U TIPVME XPSL
:PV DBO BTTFSU B UZQF GPS UIF lift FNCFEEFE JO UIF 4DPUUZ
BDUJPO
-FUƊT TFF XIBU JU EPFT -PBE UIF ƶMF BHBJO BOE DBMM UIF main
GVODUJPO :PV TIPVME TFF UIJT NFTTBHF
localhost:3000/beam
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
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
import Web.Scotty
import Web.Scotty.Internal.Types (ActionT(..))
import Control.Monad.Trans.Class
import Data.Monoid (mconcat)
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
import Control.Monad.Trans.Except
$)"15&3 45"$, Ɖ&. 61
'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
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
.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
.BZCF5
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
3FBEFS5
,FFQ JO NJOE XIBU UIFTF BSF EPJOH
GPMMPX UIF UZQFT
MJǒ UJMM
ZPV ESPQ
$)"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
import Web.Scotty
import Control.Monad.IO.Class
import Data.Monoid (mconcat)
&JUIFS5
3FBEFS5
4UBUF5
-- 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
import Control.Monad.IO.Class
import Data.Maybe (fromMaybe)
import Data.Text.Lazy (Text)
import Web.Scotty
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
4DPUUZ BHBJO
import Control.Monad.IO.Class
import Data.Text.Lazy (Text)
import Web.Scotty
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
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
"T CFGPSF
XF HFU UP CFOFƶU GSPN POF CJH CJOE VOEFS UIF
&YDFQU5
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)
)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
0ODF ZPV IBWF BO rDec UIBU XPSLT
NBLF JU BOE BOZ JOOFS
MBNCEBT QPJOUGSFF JG UIBUƊT OPU BMSFBEZ UIF DBTF
Hi: 3
Hi: 4
Hi: 5
[("1",2),("2",3),("3",4),("4",5),("5",6)]
import Control.Monad.Trans.Maybe
import Control.Monad
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
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
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
: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
.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
-- p is Player
-- c is Computer
https://en.wikipedia.org/wiki/Morra_(game)
$)"15&3 45"$, Ɖ&. 61
/POTUSJDUOFTT
$)"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
possiblyKaboom =
\f -> f fst snd (0, undefined)
(\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
possiblyKaboom b =
case b of
True -> fst tup
False -> snd tup
where tup = (0, undefined)
const x y = x
const 'a' (go "bcde") = 'a'
hypo :: IO ()
hypo = do
let x :: Int
x = undefined
s <- getLine
case s of
"hi" -> print x
_ -> putStrLn "hello"
Prelude> hypo
$)"15&3 /0/453*$5/&44
s
hello
Prelude> hypo
hi
*** Exception: Prelude.undefined
hypo' :: IO ()
hypo' = do
let x :: Integer
x = undefined
s <- getLine
case x `seq` s of
"hi" -> print x
_ -> putStrLn "hello"
Prelude> hypo'
asd
*** Exception: Prelude.undefined
let b = ???
case b of
True -> ...
False
/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
undefined `seq` y
y -> undefined
$)"15&3 /0/453*$5/&44
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
BU 'JOBMMZ
lam IBT B MBNCEB PVUTJEF UIF FYQSFTTJPO XIJDI IBT
UIF TBNF FƵFDU PO FWBMVBUJPO BT B EBUB DPOTUSVDUPS EPFT
data Test =
A Test2
| B Test2
deriving (Show)
data Test2 =
C Int
| D Int
deriving (Show)
$)"15&3 /0/453*$5/&44
2
Prelude> forceTest undefined
*** Exception: Prelude.undefined
$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
/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
forceNothing = \ _ -> I# 0#
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
}
}
discriminatory
discriminatory =
\ b_a10c ->
case b_a10c of _ {
False -> I# 0;
True -> I# 1
}
$)"15&3 /0/453*$5/&44
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
)BTLFMM BSF UIF TBNF
POF XBZ UP LOPX GPS TVSF JT CZ FYBNJOJOH
UIF $PSF
hypo'' :: IO ()
hypo'' = do
let x :: Integer
x = undefined
s <- x `seq` getLine
case s of
"hi" -> print x
_ -> putStrLn "hello"
CZZPVSMFBWF
Prelude> hypo''
*** Exception: Prelude.undefined
&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
Prelude> undefined
*** Exception: Prelude.undefined
$)"15&3 /0/453*$5/&44
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
myList = [1,2,_]
myList
|
:
/ \
1 :
/ \
2 :
/ \
_ []
myList' = (++) _ _
inc = (+1)
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
returnIO
(: ((Just (: (C# 'a') ([])))
`cast` ...) ([]))
$)"15&3 /0/453*$5/&44
returnIO
(: ((Just (unpackCString# "a"#))
`cast` ...) ([]))
1
Prelude> f 'a'
f
1
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
fm = _
Prelude> fm
Just 2
Prelude> :sprint fm
fm = _
/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> :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 = _
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
concrete
concrete = I# 1
a
a =
\ @ a1_aRN $dNum_aRP ->
fromInteger $dNum_aRP (__integer 1)
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)
-B[Z QBUUFSOT
-B[Z QBUUFSOT BSF BMTP JSSFGVUBCMF
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
#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
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# }
first (Foo x _) = x
second (Foo _ y) = y
: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
data DoesntForce =
TisLazy Int String
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
-FUƊT QMBZ XJUI UIBU JG ZPV BMSFBEZ IBWF ()$ PS OFXFS
JG OPU
UIJT DPEF XPOƊU XPSL
blah x = 1
blah x = x `seq` 1
willForce x = 1
willNotForce ~x = 1
4P FWFO XIFO ZPVƊSF VTJOH UIF 4USJDU QSBHNB
ZPV DBO TF
MFDUJWFMZ SFDPWFS MB[JOFTT XIFO EFTJSFE
data List a =
Nil
| Cons a (List a) deriving Show
Prelude> twoEls
Cons 1 (Cons *** Exception: Prelude.undefined
Prelude> oneEl
Cons 1 Nil
$)"15&3 /0/453*$5/&44
data List a =
Nil
| Cons !a (List a) deriving Show
Prelude> twoEls
$)"15&3 /0/453*$5/&44
data List a =
Nil
| Cons !a (List a) deriving Show
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
data List a =
Nil
| Cons !a !(List a) deriving Show
Prelude> twoEls
*** Exception: Prelude.undefined
Prelude> oneEl
*** Exception: Prelude.undefined
/ $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
/ UXP&MT POF&M
$POT $POT $POT /JM
$POT $POT /JM
$POT
data List a =
Nil |
Cons a (List a)
deriving (Show)
main = do
print $ take' 10 $ map' (+1) (repeat' 1)
let x = 1
let x = ['1']
let x = [1]
let x = 1 :: Int
let f = \x -> x
let x = f 1
let x = undefined
let y = x `seq` 1 in snd (x, y)
const 1 undefined
const undefined 1
$)"15&3 /0/453*$5/&44
x = undefined
y = "blah"
main = do
print (snd (x, y))
4FRVFODF QPJOU
https://en.wikipedia.org/wiki/Sequence_point
#BTJD MJCSBSJFT
-JOVT 5PSWBMET
$)"15&3 #"4*$ -*#3"3*&4
-- with stack
$ stack ghc -- -O2 bench.hs
-- without stack
$ ghc -O2 bench.hs
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
]
_ !? n | n < 0 = Nothing
[] !? _ = Nothing
(x:_) !? 0 = Just x
(_:xs) !? n = xs !? (n-1)
-- Self function call, not yet in weak head.
[1, 2, 3] !? 2
-- matches final case
[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
#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
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
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
import Criterion.Main
import Debug.Trace
myList :: [Int]
myList = trace "myList was evaluated"
([1..9999] ++ [undefined])
main :: IO ()
main = defaultMain
[ bench "index list 9999"
$ whnf (myList !!) 9998
, bench "index list maybe index 9999"
$ nf (myList !?) 9999
]
import Criterion.Main
myList :: [Int]
myList = [1..9999]
main :: IO ()
main = defaultMain
[ bench "map list 9999" $ whnf (map (+1)) myList
]
(_ : _)
"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])
-- into:
nf (map (+1)) myList
5IFO XF HFU
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
import Control.Monad
blah :: [Integer]
blah = [1..1000]
main :: IO ()
main =
replicateM_ 10000 (print blah)
*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
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)
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
$"'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
-- not a CAF
incdInts :: [Integer] -> [Integer]
incdInts x = map (+1) x
main :: IO ()
main = do
print (incdInts [1..] !! 1000)
CAF
main
incdInts
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
import Criterion.Main
import qualified Data.Map as M
main :: IO ()
main = defaultMain
[ bench "lookup one thing, list" $
whnf (lookup "doesntExist") pairList
, bench "lookup one thing, map" $
whnf (M.lookup "doesntExist") testMap
]
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
import Criterion.Main
import qualified Data.Map as M
import qualified Data.Set as S
bumpIt (i, v) = (i + 1, v + 1)
s :: S.Set Int
s = S.fromList $ take 10000 stream
where stream = iterate (+1) 0
$)"15&3 #"4*$ -*#3"3*&4
main :: IO ()
main = defaultMain
[ bench "member check map" $
whnf membersMap 9999
, bench "member check set" $
whnf membersSet 9999
]
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
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
import Criterion.Main
import qualified Data.Sequence as S
lists :: [[Int]]
lists = replicate 10 [1..100000]
main :: IO ()
main = defaultMain
[ bench "concatenate lists" $
nf mconcat lists
, bench "concatenate sequences" $
nf mconcat seqs
]
import Criterion.Main
import qualified Data.Sequence as S
lists :: [Int]
lists = [1..100000]
main :: IO ()
main = defaultMain
[ bench "indexing list" $
whnf (\xs -> xs !! 9001) lists
, bench "indexing sequence" $
whnf (flip S.index 9001) seqs
]
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
import Criterion.Main
import qualified Data.Vector as V
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
]
-- from Data.Vector
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
import Criterion.Main
import qualified Data.Vector as V
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
import Criterion.Main
import Data.Vector ((//))
import qualified Data.Vector as V
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
.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
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
main :: IO ()
main = defaultMain
[ bench "mutable IO vector"
$ whnfIO (mutableUpdateIO 9998)
, bench "mutable ST vector"
$ whnf mutableUpdateST 9998
]
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
type STRep s a =
GHC.Prim.State# s -> (# GHC.Prim.State# s, a #)
&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
: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
import Control.Monad
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import qualified System.IO as SIO
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
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)
#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
module BS where
input :: BL.ByteString
input = "123"
compressed :: BL.ByteString
compressed = GZip.compress input
main :: IO ()
main = do
TIO.putStrLn $ TE.decodeUtf8 (s input)
TIO.putStrLn $ TE.decodeUtf8 (s compressed)
where s = BL.toStrict
#ZUF4USJOH USBQT
throwsException :: IO ()
throwsException =
utf8ThenPrint (B8.pack s)
bytesByWayOfText :: B.ByteString
bytesByWayOfText = TE.encodeUtf8 (T.pack s)
$)"15&3 #"4*$ -*#3"3*&4
thisWorks :: IO ()
thisWorks = utf8ThenPrint bytesByWayOfText
alsoWorks :: IO ()
alsoWorks = utf8ThenPrint libraryDoesTheWork
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
12435
-- 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
empty :: DList a
empty = undefined
{-# INLINE empty #-}
-- Append dlists.
append :: DList a -> DList a -> DList a
append = undefined
{-# INLINE append #-}
main :: IO ()
main = defaultMain
[ bench "concat list" $ whnf schlemiel 123456
, bench "concat dlist" $ whnf constructDlist 123456
]
-- adds an item
push :: a -> Queue a -> Queue a
push = 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
*0
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
-- 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
XJUI PS DPOUSPM JO UIF XBZ ZPVƊE FYQFDU GSPN UIF PUIFS 4UBUF
UZQFT
8IBU
/P
SFBMMZ 5IBUƊT B MPU PG JU
main = do
putStr "1"
putStr "2"
putStrLn "3"
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
-- from Data.Time.Clock
getCurrentTime :: IO UTCTime
getCurrentTime :: IO UTCTime
-- ^-- that right there
"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
import Control.Concurrent
main :: IO ()
main = do
mv <- myData
putMVar mv 0
mv' <- myData
zero <- takeMVar mv'
print zero
take
put
take
put
put
take
take
Prelude> main
$)"15&3 *0
*** Exception:
thread blocked indefinitely in an MVar operation
IO String
mv mv'
put take (the final one)
IO (MVar a)
import Debug.Trace
blah :: IO String
blah = return "blah"
"OE GPS woot XFƊMM VTF inner trace JOTJEF UIF *0 BDUJPO
woot :: IO String
woot = return (trace "inner trace" "woot")
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
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
5IF *0 'VODUPS
8IBU EPFT GNBQ NFBO XJUI SFTQFDU UP *0 "T BMXBZT
XF XBOU
BO FYBNQMF
"QQMJDBUJWF BOE *0
*0 BMTP IBT BO "QQMJDBUJWF JOTUBODF
BT XF NFOUJPOFE JO UIF
"QQMJDBUJWF DIBQUFS :PV NJHIU SFNFNCFS BO FYBNQMF MJLF
UIJT
.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
import Data.Time.Calendar
import Data.Time.Clock
import System.Random
.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
import Control.Concurrent
main :: IO ()
main = do
mv <- newEmptyMVar
putMVar mv (0 :: Int)
zero <- takeMVar mv
print zero
import Control.Concurrent
import System.IO.Unsafe
main :: IO ()
main = do
putMVar myData 0
zero <- takeMVar myData
print zero
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
$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
*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/(
data BlockedIndefinitelyOnMVar =
BlockedIndefinitelyOnMVar
-- Defined in ‘GHC.IO.Exception’
data ArithException
= Overflow
| Underflow
| LossOfPrecision
| DivideByZero
| Denormal
| RatioZeroDenominator
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/(
data SomeException =
forall e . Exception e => SomeException e
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/(
data MyException =
forall e .
(Show e, Typeable e) => MyException 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/(
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)
Prelude> runDisc 0
Arith divide by zero
Prelude> runDisc 1
Async stack overflow
Prelude> runDisc 2
SomethingElse
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
Prelude> 2 `div` 0
*** Exception: divide by zero
-- 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
$ ./wp
wrote to file
$ cat aaa
hi
$ touch zzz
$ chmod 400 zzz
-- 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)
import Control.Exception
import Data.Typeable
main =
writeFile "zzz" "hi"
`catch` handler
-- writePls.hs
module Main where
import Control.Exception
import Data.Typeable
main =
writeFile "zzz" "hi"
`catch` handler
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
-- Control.Exception
try :: Exception e => IO a -> IO (Either e a)
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
onlyReportError :: Show e
=> IO (Either e a)
-> IO ()
onlyReportError action = do
result <- action
case result of
Left e -> print e
Right _ -> return ()
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/(
main :: IO ()
main = do
args <- getArgs
mapM_ testDiv args
Prelude> :main 4 5 0 9
1
1
divide by zero
0
import Control.Exception
canICatch :: Exception e
=> e
-> IO (Either ArithException ())
canICatch e =
try $ throwIO e
$)"15&3 8)&/ 5)*/(4 (0 830/(
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/(
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)
import Control.Exception
main :: IO ()
main = do
throwIO DivideByZero
putStrLn "lol"
Prelude> main
*** Exception: divide by zero
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 ...
import Control.Exception
data NotDivThree =
NotDivThree
deriving (Eq, Show)
data NotEven =
NotEven
deriving (Eq, Show)
*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
"EEJOH DPOUFYU
$POWFOJFOU TVCTFDUJPO UJUMJOH "OZIPX
MFUƊT NPEJGZ UIBU
import Control.Exception
$)"15&3 8)&/ 5)*/(4 (0 830/(
data NotDivThree =
NotDivThree Int
deriving (Eq, Show)
data NotEven =
NotEven Int
deriving (Eq, Show)
*OurExceptions> evenAndThreeDiv 12
12
*OurExceptions> evenAndThreeDiv 9
*** Exception: NotEven 9
*OurExceptions> evenAndThreeDiv 8
$)"15&3 8)&/ 5)*/(4 (0 830/(
catchNotDivThree :: IO Int
-> (NotDivThree -> IO Int)
-> IO Int
catchNotDivThree = catch
catchNotEven :: IO Int
-> (NotDivThree -> IO Int)
-> IO Int
catchNotEven = catch
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
import Control.Exception
data EATD =
NotEven Int
| NotDivThree Int
deriving (Eq, Show)
import Control.Exception
%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
openAndWrite :: IO ()
openAndWrite = do
h <- openFile "test.dat" WriteMode
threadDelay 1500
hPutStr h (replicate 100000000 '0' ++ "abc")
hClose h
data PleaseDie =
PleaseDie
deriving Show
main :: IO ()
main = do
threadId <- forkIO openAndWrite
threadDelay 1000
throwTo threadId PleaseDie
$)"15&3 8)&/ 5)*/(4 (0 830/(
openAndWrite :: IO ()
openAndWrite = do
h <- openFile "test.dat" AppendMode
threadDelay 1500
hPutStr h (replicate 10000000 '0' ++ "abc")
hClose h
data PleaseDie =
PleaseDie
deriving Show
main :: IO ()
main = do
threadId <- forkIO (mask_ openAndWrite)
threadDelay 1000
throwTo threadId PleaseDie
$)"15&3 8)&/ 5)*/(4 (0 830/(
%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
'JOBM QSPKFDU
$)"15&3 '*/"- 130+&$5
Ƒ '*/(&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
$ finger callen@localhost
Login: callen Name: callen
Directory: /home/callen Shell: /bin/zsh
$ finger callen
Login: callen Name: Christopher Allen
Directory: /Users/callen Shell: /bin/bash
1SPKFDU PWFSWJFX
5P LJDL UIJT PƵ
XFƊMM VTF 4UBDL XJUI UIF stack new DPNNBOE
MJLF TP
$ 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
/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
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
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
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
$ telnet localhost 79
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
blah
blah
Connection closed by foreign host.
"blah\r\n"
$)"15&3 '*/"- 130+&$5
$ finger callen@localhost
[localhost]
Trying 127.0.0.1...
callen
$ finger @localhost
[localhost]
Trying 127.0.0.1...
Trying ::1...
finger: connect: Connection refused
Trying 127.0.0.1...
"callen\r\n"
"\r\n"
'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
data Blah =
Blah { myThing :: Int }
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)
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
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
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
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)
type UserRow =
(Null, Text, Text, Text, Text, Text)
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")
#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
*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
$ stack build
$ sudo `stack exec which fingerd`
$ finger callen@localhost
Login: callen Name: Chris Allen
Directory: /home/callen Shell: /bin/zsh
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