Your SlideShare is downloading. ×
0
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
[Не]практичные типы
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

[Не]практичные типы

1,238

Published on

Презентация, которая была сделана на 11-ой встрече коммьюнити Software Craftsmanship BY

Презентация, которая была сделана на 11-ой встрече коммьюнити Software Craftsmanship BY

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,238
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
10
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. практичные типы Software Craftsmanship BY, @remeniuk λ
  • 2. в теориисистема типов - статическая аппроксимацияпрограммы во время выполнения Бенжамин Пирс, "TAPL" что дают типы? производительность безопасность документорованность оптимизации компилятора лучшие абстракции одни достоинства
  • 3. в мейнстримеpublic Map<Desk<Poker>, List<Player<Poker>>getPlayersPerDesks(){ Map<Desk<Poker>, List<Player<Poker>> players= new HashMap<Desk<Poker>, List<Player<Poker>>(); ... return players;} boilerplate
  • 4. Бенжамин Пирс приукрашал картину?нет. просто он говорил не о Java(C#, C++, ..)
  • 5. 1, true, "abc" - термы / конкретные значения / абстракции нулевого порядка x => x + 1 - функция / абстракции первого порядка (полиморфны, т.к. конструируют множественные конкретные значения)* Int, Boolean, String конкретные типы* -> * List[T], Map[K, V] функции на типах / полиморфные типы / конструкторы типов
  • 6. (* -> *) -> *trait Functor[F[_]] { def map[A, B](r: F[A], f: A => B): F[B]}map - функция высшего порядка; в качествепереметра приниимает функцииFunctor - тип высшего порядка; в качествепараметров принимает конструкторы типов
  • 7. λ-куб Fω<: Fω CCF<: F λωλ<: λ-> LF
  • 8. Fω<:
  • 9. вариантность типов и System F<: F<: F λ<: λ->
  • 10. вариантность типов и System F<:S подтип T, конструктор типов C<U> => C<S> подтип/супертип/? C<T>
  • 11. вариантность типов в Javacписки ковариантны: S[] подтип T[]oстальные типы - инвариантыworkaround: имитация вариантности в местевызова с помощью органиченныхэкзистенциальных типовList<? extends List<? extends Number>> l = new ArrayList<List<Number>>();
  • 12. вариантность типов в ScalaC[+U] - ковариантность, S подтип T => C[S] подтип C[T]C[-U] - контрвариантность, S подтип T => C[T] супертип C[S]С[U] - инвариантность (как в Java), S подтип T => C[T] ? C[S]
  • 13. trait Suittrait Spades extends Suitclass Card[T <: Suit](rank: String)class Hand[A <: Suit](cards: List[Card[A]] = Nil) { def add[B >: A <: Suit](card: Card[B]): Hand[B] = new Hand[B](card :: cards)}val hand1: Hand[Spades] = new Hand.add(new Card[Spades]("A")).add(new Card[Spades]("Q"))val hand2: Hand[Suit] = new Hand.add(new Card[Spades]("A")).add(new Card[Hearts]("Q"))
  • 14. trait Suittrait Spades extends Suitclass Card[+T <: Suit](rank: String)class Hand[A <: Suit](cards: List[Card[A]] = Nil) { def add[B >: A <: Suit](card: Card[B]): Hand[B] = new Hand[B](card :: cards)}val hand1: Hand[Spades] = new Hand.add(new Card[Spades]("A")).add(new Card[Spades]("Q"))val hand2: Hand[Suit] = new Hand.add(new Card[Spades]("A")).add(new Card[Hearts]("Q"))
  • 15. class HandEvaluator[T <: Suit] (val evaluate: List[Card[T]] => Int)val flushEval = new HandEvaluator( (_: List[Card[Spades]]) => 1000)val genEval = new HandEvaluator( (_: List[Card[Suit]]) => 100)val hand1: Hand[Spades] = ... > println(hand1.evaluate(flushEval)) 1000 > println(hand1.evaluate(genEval)) Suit >:Spades, but class HandEvaluator is invariant in type T
  • 16. class HandEvaluator[-T <: Suit] (val evaluate: List[Card[T]] => Int)val flushEval = new HandEvaluator( (_: List[Card[Spades]]) => 1000)val genEval = new HandEvaluator( (_: List[Card[Suit]]) => 100)val hand1: Hand[Spades] = ...> println(hand1.evaluate(flushEval))1000> println(hand1.evaluate(genEval))100
  • 17. неявная конверсия типов1. class A { def foo(): Unit }2. class B ...магия...3. val b = new B() b.foo() // b был неявно конвертирован в A [[A -> B]]
  • 18. неявная конверсия типовtrait Cardclass Hand(cards: List[Card]) { def weight = /*..*/ }object Hand { implicit def toHand(cards: List[Card]) = new Hand(cards)} import Hand._ List[Card]().weight неявный контексттип List[Card] "видимый как" Hand
  • 19. ограничения на "вид"class HandComparator { def compare[T <% Hand](hand1: T, hand2: T) = hand1.weight compareTo hand2.weight}new HandComparator().compare(new Hand(Nil), new Hand(Nil))new HandComparator().compare(List[Card](), List[Card]())
  • 20. ограничения на контекстclass Hand[A <: Suit](cards: List[Card[A]] = Nil) { def add[B >: A <: Suit](card: Card[B]): Hand[B] =new Hand[B](card :: cards) def evaluate(evaluator: HandEvaluator[A]) =evaluator.evaluate(cards)}val flushEval = new HandEvaluator( (_: List[Card[Spades]]) => 1000)val genEval = new HandEvaluator( (_: List[Card[Suit]]) => 100)
  • 21. ограничения на контекстclass Hand[A <: Suit](cards: List[Card[A]] = Nil) { def add[B >: A <: Suit](card: Card[B]): Hand[B] =new Hand[B](card :: cards) def evaluate(evaluator: HandEvaluator[A]) =evaluator.evaluate(cards)} помещаем в неявный контекстimplicit val flushEval = new HandEvaluator( (_: List[Card[Spades]]) => 1000)implicit val genEval = new HandEvaluator( (_: List[Card[Suit]]) => 100)
  • 22. ограничения на контекстclass Hand[A <: Suit : HandEvaluator](cards: List[Card[A]] =Nil) { def add[B >: A <: Suit](card: Card[B]): Hand[B] =new Hand[B](card :: cards) def evaluate = implicitly[HandEvaluator[A]].evaluate(cards)}implicit val flushEval = new HandEvaluator( (_: List[Card[Spades]]) => 1000)implicit val genEval = new HandEvaluator( (_: List[Card[Suit]]) => 100)
  • 23. ограничения на контекстval h1 = Hand().add(Card[Hearts]("A")).add(Card[Hearts]("Q"))val h2 = Hand().add(Card[Spades]("A")).add(Card[Spades]("Q"))val h3 = Hand().add(Card[Spades]("A")).add(Card[Hearts]("Q"))> println(h1.evaluate)could not find implicit value for evidence parameter oftype by.scala.pokertypes.variance.HandEvaluator[B]> println(h2.evaluate)1000> println(h3.evaluate)100
  • 24. реификация vs стирание типовC#, F# (CLR) реализует реификацию типов, но неподдерживает типы высших порядковJava (JVM) стирает типы, и не поддерживаеттипы высших порядковScala имитирует реификацию, и поддерживаеттипы высших порядков
  • 25. имитация реификацииdef evaluate[T <: Suit : Manifest](hand: Hand[T]) = { print("Type parameter class: " + manifest[T].erasure) if (manifest[T] <:< manifest[Spades]) print("; Spades") else print("; Random")}val h2 = Hand().add(Card[Spades]("A")).add(Card[Spades]("Q")) > println(evaluate(hand1)) Type parameter class: interface Spades; Spades > println(evaluate(hand2)) Type parameter class: interface Suit; Random
  • 26. зависимые типыλ-> LF
  • 27. зависимые типыcase class Desk(id: Int) { case class Action(name: String) def log(action: Action) = /*..*/}desk1.log(desk1.Action("Small Blind"))desk1.log(desk2.Action("Small Blind")) // не компилируется
  • 28. черная магия типы-фантомы тип-объеднение и гетерогенныесписки
  • 29. class Dealer[T <: Stage : Manifest](deck: List[Card]) { def deal(cards: Int, recipient: Actor): Dealer = /*...*/} если бы мы могли гарантировать на уровне типов, что дилер выдаст всем нужное количество кард...
  • 30. типы-фантомыsealed trait Stagetrait Preflop extends Stagetrait Flop extends Stagetrait Turn extends Stagetrait River extends Stagetrait Showdown extends Stagetrait StageOrder[Last <: Stage, Current <: Stage]implicit val gotoFlop = new StageOrder[Preflop, Flop] {}implicit val gotoTurn = new StageOrder[Flop, Turn] {}implicit val gotoRiver = new StageOrder[Turn, River] {}
  • 31. типы-фантомыclass Dealer[LastStage <: Stage](deck: List[Card]) { type IsCurrentStageValid[T <: Stage] = StageOrder[LastStage, T] def deal[CurrentStage <: Stage : IsCurrentStageValid] (recipient: Actor): Dealer[CurrentStage] = {/*...*/}}dealer.deal[Flop](desk).deal[Turn](desk).deal[River](desk)dealer.deal[Flop](desk).deal[Flop](desk).deal[River](desk)
  • 32. trait HandEvaluator { def compare(hand1: List[Card], hand2: List[Card]): Int} если бы мы могли проверять не только тип списка, но и его содержимое...
  • 33. гетерогенный списокclass Cardobject Card { type NoCards = HNil type HandCards = Card :: Card :: NoCards type FlopCards = Card :: Card :: Card :: NoCards type TurnCards = Card :: FlopCards type RiverCards = Card :: TurnCards}
  • 34. гетерогенный список и тип-объединениеtrait HandEvaluator { def compare[T: (HandCards ∨ (RiverCards :: HandCards))#λ] (hand1: T, hand2: T): Int}val handCards = new Card :: new Card :: HNilval communityCards = new Card :: new Card :: new Card :: newCard :: new Card :: HNil handEvaluator.compare(handCards, handCards) handEvaluator.compare(communityCards :: handCards, communityCards :: handCards) handEvaluator.compare(handCards, communityCards)

×