AnhĂ€nger der funktionalen Programmierung locken Neulinge gerne mit dem Versprechen perfekter Code-Ausdruckskraft, 100% iger Korrektheit, einfacher UnterstĂŒtzung und einfacher Umgestaltung und sagen manchmal sogar die höchste Leistung voraus. Erfahrene Entwickler wissen jedoch, dass dies nicht der Fall ist. Programmieren ist harte Arbeit und âmagische Pillenâ gibt es nicht.
Andererseits sind Elemente eines funktionalen Programmierstils bereits in industrielle Programmiersprachen wie Swift und Kotlin eingedrungen. Die Entwickler dieser Sprachen sind mit der funktionalen Programmierung bestens vertraut, sodass sie sie âim Kleinenâ verwenden konnten und viele, wenn auch nicht alle der erforderlichen Komponenten bereitstellten. Je weiter - desto mehr Teile der FI werden in industrielle Atomwaffen eingefĂŒhrt und desto besser und umfassender wird die UnterstĂŒtzung umgesetzt.
In der Lage zu sein, in einem funktionalen Stil zu programmieren, ist nĂŒtzlich, um Ihre Arbeit zu vereinfachen, und jetzt werden wir sehen, wie man es benutzt!
Vitaly Bragilevsky ist Lehrer fĂŒr FP, Theorie der Algorithmen und Berechnung, Autor des Buches "Haskell in Depth" und Mitglied der Haskell 2020-Komitees und des Ăberwachungskomitees des GHC-Compilers.
Kurze Geschichte
Funktionale Programmiergeschichten sind nicht immer wahr. Oft wird so ĂŒber AF gesprochen.
âEs war einmal in einer fernen Galaxie, die Programmierung war einfach, unkompliziert und gut. Algorithmen und Datenstrukturen sind programmiert und alles ist in Ordnung - keine Probleme!
Dann kamen die beĂ€ngstigenden Sith- Leute, die entschieden, dass alle Programme aus Klassen bestehen: '' Objektorientierte Programmierung fĂŒr alle! Alles muss nur mit solchen Methoden geschrieben werden. ''
Als sie an StĂ€rke gewannen, wurde es unmöglich, Software zu entwickeln - es traten viele Probleme auf. Um die unglĂŒcklichen leidenden Entwickler zu retten, gibt es funktionale Programmierung. "Die Hauptsache bei der Errettung ist es, ein schönes und bedeutungsloses Bild zu zeichnen.

Wenn Sie alles auf dem Bild anwenden, werden GlĂŒck, Frieden und Ruhe kommen und die Probleme der Softwareentwicklung werden gelöst.
Die Geschichte ist wunderschön, aber in Wirklichkeit ist alles anders. So vertrete ich funktionale und industrielle Programmierung.

Funktionale Programmierung ist das Labor von Faraday - der Geburtsort von Ideen, die dann in der industriellen Programmierung angewendet werden.
In einem GesprĂ€ch ĂŒber industrielle Programmiersprachen sollten die Konzepte, ob sie funktionsfĂ€hig sind oder nicht, ob sie FP verwenden oder nicht, nicht angesprochen werden!
Die Hauptaufgabe der FP ist es, den Mainstream-Sprachen gute Elemente zu vermitteln.
Alle auf funktionierende Schienen ĂŒbertragen zu wollen, ist dasselbe wie Wissenschaftler zu Experimenten wie Faraday zu zwingen - es macht keinen Sinn. Derzeit fĂŒhrt niemand Experimente mit so veralteten Methoden zur ElektrizitĂ€t durch.
Schauen wir uns Beispiele an.
John McCarthy Funktion
John McCarthy ist einer der Schöpfer von Lisp.

Fortran war vor 65 Jahren die Hauptprogrammiersprache. Es hat eine bedingte Aussage:
IF (I.NE.0) GOTO 40
STMT-1
STMT-2
40 STMT-3
I 0, «40».
, , . ,
XIF(M, N1,N2)
, , : N1 N2.
: «⊠» , .
â N1 N2. , ?
:
M==0 ? N1 : N2
. . , , - .
?
â . 1977 . « ?». â â , .

â , .
- :
c := 0
for i := 1 step 1 until n do
c := c + a[i]*b[i]
â .
. FP.
Def DotP = (Insert +) o (ApplyToAll x) o Transpose
â
o
, , , .
â â , , .
. .
, - Java . , , , .

, , :
, .
:
fun countLinesInFiles(fnames: List<String>): Int
= fnames.map { File(it).readLines().size }
.sum()
Kotlin, , . ?
, , .
â «map» â .
, : , . it â . â sum().
,
map
Kotlin, , . , . â
readLines
.
Haskell
, Haskell.
countLines :: FilePath -> IO Int
countLines = fmap (length . lines) . readFile
countLinesInFiles :: [FilePath] -> IO Int
countLinesInFiles = fmap sum . traverse countLines
, , . Haskell , , .
. , : , Int â .
. «IO», Haskell ,
-. « », Int, IO Int. , .
. â Haskell. â FilePath, IO Int â . : , traverse â , «countLines».
. «. » (
o
) â . , .
«f. g» â , «x» «f(g(x))». , . , . .
.
, , . â , .
UML-. : , , , , .

Swift
, , - . Swift , , .
protocol Shape {
func area() -> Double
func diameter() -> Double
}
class Circle: Shape {
var r = 0.0
init(radius: Double) {
r = radius
}
func area() -> Double {
return 3.14 * r * r
}
func diameter() -> Double {
return 2 * r
}
}
class Square: Shape {
var s = 0.0
init(size: Double) {
s = size
}
func area() -> Double {
return s * s
}
func diameter() -> Double {
return sqrt(2) * s
}
}
, .
: , , â , . .
, , .
func testShape(shape: Shape) {
print(shape.area())
print(shape.diameter())
}
. .
testShape(shape: Circle(radius: 5))
testShape(shape: Square(size: 5))
78.5
10.0
25.0
7.0710678118654755
, , , , - . â , .
Haskell
Haskell, , Swift.
data Shape = Circle Double | Square Double
area :: Shape -> Double
area (Circle r) = 3.14 * r * r
area (Square s) = s * s
diameter :: Shape -> Double
diameter (Circle r) = 2* r
diameter (Square s) = sqrt 2 * s
. , « » â . «» . .
â , , . Haskell â . , .
:
> area (Circle 5)
78.5
> diameter (Circle 5)
10.0
> area (Square 5)
25.0
diameter (Square 5)
7.0710678118654755
â â , .
, Swift Haskell .
, ,
, . , , â , â , , .
â , â . â , .
, : ? . .
, :
â .
, Swift.
HaskellâŠ
data Shape = Circle Double | Square Double
⊠Swift .
enum Shape {
case Circle(radius: Double)
case Square(size: Double)
}
. «» , Swift «enum», . , .
HaskellâŠ
area :: Shape -> Double
area (Circle r) = 3.14 * r * r
area (Square s) = s * s
⊠Swift .
extension Shape {
var area: Double {
switch self {
case .Circle(let r): return 3.14 * r * r
case .Square(let s): return s * s
}
}
}
, â .
Kotlin:
sealed class Shape {
data class Circle(val radius: Double): Shape()
data class Square(val size: Double): Shape()
}
fun area(sh: Shape): Double {
return when (sh) {
is Shape.Circle -> 3.14 * sh.radius * sh.radius
is Shape.Square -> sh.size * sh.size
}
}
, â .
, Kotlin Swift ? , , , . , -, .
. , , , , , .
, , , - â . . : â . , , .
. .
. . â - , â , . â .
â â . 20 , .
- «Visitor». , , . , .
- .
- â .
- .
- .
, « », . . , â , .
, .
, : , , , . , .

Haskell. , , , «» ?
, «» â .
â «Composite». . , .
, Kotlin â .
val a = "Hello "
val b = "world"
val c = a + b
, : «, ? ». , â
- .
â HTTP-. Kotlin :
val a = HttpReq("f","v1")
val b = HttpReq("f2","v2")
val c = a + b
Haskell , . HTTP- â . HTTP-.
.
. - . â , â , . «optional chaining», , Swift.
if let johnsStreet = john.residence?.address?.street
{ /* SUCCESS */ } else { /* FAILURE */ }
, . «john» â .
: , , . â . , else â . .
Swift . , , , : .
Haskell, .
case residence john >>= address >>= street of
Just johnsStreet -> -- SUCCESS
Nothing -> -- FAILURE
,
«>>=» â . .
Swift «optional chaining» . Kotlin . Haskell , «>>=».
:
. . , . , â , .
, â .
«» . â , . «», . « » .
â ?
. , â .
,
â . Haskell
«Build Systems a la Carte» . Distinguished Paper Award International Conference on Functional Programming (ICFP) - 2018 . Build-, .
Build- Build- â . .
data Store i k v
:
- i â ;
- k â , , ;
- v â , , , .
â . â , . .
. , , . , - -, , .
â
«Task» â .
newtype Task c k v = Task { run :: forall f. c f => (k -> f v) -> f v }
Haskell, . , â «f», . , .
? «k -> fv» â - . . . Build-.
â :
type Tasks c k v = k -> Maybe (Task c k v)
, , . «Maybe» â - «optional». , - - , .
Build-:
type Build c i k v = Tasks c k v -> k -> Store i k v
-> Store i k v
. k, . â . , .
.
- Make,
- Shake â Make Haskell,
- Bazel,
- Excel.
. â Excel â . Excel â . , - . Make Excel - , .
â
.
â Haskell . , ., . - â . , , . ,
.
, Haskell:
h :: [a] -> Int
h = length . filter p . map g . map f
â . - , :
map f
â f
;map g
â g
;filter p
â : , , ;length
â â .
:
â , , ⊠! !, .
Fusion
«fusion», .
«fusion»? -: :
c := 0
foreach (x : xs)
if p(g(f(x)))
then c := c + 1
,
(!),
(!). , , 2-3 .
, , , . â .
, .
GPU? !
Haskell, :
dotp :: Acc (Vector Float) -> Acc (Vector Float) -> Acc (Scalar Float)
dotp xs ys = fold (+) 0 (zipWith (*) xs ys)
, Haskell: 2 , , . , Haskell GPU. GPU, : CUDA, Open CL â , . Accelerate Haskell â .
CUDA 100 , , . ! , . , .
â . ? a, b, c D.
f :: A -> B -> C -> D
f a b c = ...
, â . , :
f :: A -> B -> C -> D
f a :: B -> C -> D
f a b :: C -> D
f a b c :: D
, . , , - , . â , , .
, , Scala -.
f :: A -> (B , C) -> D
f a p = âŠ
f :: A -> B -> C -> D
f a :: (B, C) -> D
f a p :: D
: « , . , . , â ». .
, .
. Haskell 15 QuickCheck, .
, , :
reverse :: String -> String
reverse = ...
, . , .
> quickCheck (\s -> reverse (reverse s) == s)
+++ OK, passed 100 tests.
, . , 100, , , .
, , . . Haskell 15 . . , Swift Kotlin .
, ?
abs :: Int -> Int
abs x = if x < 0 then 0 - x else x
head :: [a] -> a -- !
head (x:_) = x
example :: Int -> Int
example x = if abs x < 0 then head [] else x
,
.
head :: [a] -> a -- !
head (x:_) = x
,
head
, â .
«head», ? , LiquidHaskell . LiquidHaskell â Haskell-.
{-@ abs :: Int -> { n : Int | 0 <= n } @-}
abs :: Int -> Int
abs x = if x < 0 then 0 - x else x
{-@ head :: { xs : [a] | 1 <= len xs } -> a @-}
head :: [a] -> a -- !
head (x:_) = x
{-@ head :: { xs : [a] | 1 <= len xs } -> a @-}
head :: [a] -> a -- !
head (x:_) = x
, abs , n.
{-@ abs :: Int -> { n : Int | 0 <= n } @-}
abs :: Int -> Int
abs x = if x < 0 then 0 - x else x
, .
{-@ head :: { xs : [a] | 1 <= len xs } -> a @-}
head :: [a] -> a -- !
head (x:_) = x
, , . x x.
{-@ example :: x : Int -> { y : Int | x == y } @-}
example :: Int -> Int
example x = if abs x < 0 then head [] else x
, . , . , - . - - , , Eiffel, - .
?
-:
type MyAPI = Get '[PlainText] String
:<|> "conf" :> Get '[JSON] String
:<|> "year" :> Get '[JSON] Int
:<|> "like" :> Get '[JSON] Bool
myAPI :: Server MyAPI
= root :<|> year :<|> conf :<|> like
Haskell Servant, API . , url , , , JSON. , : String», Int», Bool.
.
root :: Handler String
root = pure "Welcome to my REST API"
conf :: Handler String
conf = pure "AppsConf"
year :: Handler Int
year = pure 2019 conf
like :: Handler Bool
like = pure True
â , .
, . , , . â .
â . , . .
â
« Haskell». 2018 . , . Haskell. 600 , .
«Haskell in Depth» . , , . «slbragilevsky» 42%.
Saint AppsConf , Introductory- , . , , . , iOS, Android, - â . , , .
telegram-, .