На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (495) « Первая ... 424 425 [426] 427 428 ...  494 495  ( Перейти к последнему сообщению )  
> Delphi vs C++ vs C# , ну и Java немножко, где-то ближе к старшему байту номеров страниц
    Цитата korvin @
    Несимметрично != вводится пользователем

    Гля, вы гениальны! А я и не догадывался! (если кто не понял - это вариация на тему "спасибо, кэп").
    Цитата korvin @
    Да пожалуйста:

    Давайте серьёзно, а? А то второй раз меня забанят...
    Вы же прекрасно поняли, что длина подобного списка вводится пользователем.
      Цитата korvin @
      Да пожалуйста:
      ExpandedWrap disabled
        xs = Cons 1 $ Cons 2 $ Cons 3 Nil
        ys = Cons 1 $ Cons 2 Nil

      списки построены независимо, при этом имеют разные типы, поэтому не пройдут в (scalarProduct xs ys) еще на этапе компиляции

      Так это статически построенные списки.

      Цитата
      Цитата D_KEY @
      Я не увидел пользы в примере с двумя списками.

      Почему? Попробуй абстрагироваться от способа создания списков. Суть в том, что сигнатура функции test' (и scalarProduct) не позволит применить ее к двум спискам разной длины, на этапе компиляции.

      Это функции занимаются и конструированием списка, и вычислением итогового результата. Это совершенно бессмысленно в реальных условиях.
        Цитата D_KEY @
        Это функции занимаются и конструированием списка, и вычислением итогового результата. Это совершенно бессмысленно в реальных условиях.

        scalarProduct не занимается конструированием списка так-то, а test' не занимается вычислением результата.

        Вот еще со статическим map

        ExpandedWrap disabled
          import System
           
          data Nil = Nil
          data Cons a = Cons Integer a
           
           
          class List a where
              lmap :: (Integer -> Integer) -> a -> a
           
          instance List Nil where
              lmap _ Nil = Nil
           
          instance List a => List (Cons a) where
              lmap f (Cons n a) = Cons (f n) $ lmap f a
           
           
          class List a => ScalarProduct a where
              scalarProduct :: a -> a -> Integer
           
          instance ScalarProduct Nil where
              scalarProduct Nil Nil = 0
           
          instance ScalarProduct a => ScalarProduct (Cons a) where
              scalarProduct (Cons n1 a1) (Cons n2 a2) = n1 * n2 + scalarProduct a1 a2
           
           
          fx i = 2*i + 1
          fy i = i^2
           
          test :: Integer -> Integer
          test n = test' n 0 Nil Nil where
              test' :: ScalarProduct a => Integer -> Integer -> a -> a -> Integer
              test' 0 _ xs ys = scalarProduct (lmap fx xs) (lmap fy ys)
              test' n i xs ys = test' (n-1) (i+1) (Cons i xs) (Cons i ys)
           
          main :: IO ()
          main = print . test . read . head =<< getArgs



        Вот, кстати, сегодня еще наткнулся на любопытный пост:

        Цитата

        вот на счет контрактов часто жалуются. а что толку от контрактов, если они не проверяются на практике.
        дак вот, встретил на рсдн хороший пост:
        http://rsdn.ru/forum/decl/4522924.flat.aspx

        там правда примеры сложноватые для нехаскелистов, поэтому как будет время(на днях), напишу пару игрушечных примера. что бы без разных монадныых трансформеров

        суть топика такова. параметризируем монаду двумя типами: пост- и пред- условиями.
        что получаем на практике - проверку контракта в момент компиляции.

        пример(игрушечную модель которого я напишу сегодня или завтра): есть у нас файл. в него можно писать, только если он открыт для записи. закрывать только если он открыт. и если он закрыт, то писать в него нельзя.

        что нам предлагают современные языки(а вернее их библиотеки). если мы попытаемся писать в закрытый файл, то получим исключение в рантайме.
        но параметризированные монады позволяют отловить данную ошибку - в момент компиляции.

          А я вот всё ещё не понял. Так списки совсем динамические, или динамически просто заполняются?
            Цитата korvin @
            Вот, кстати, сегодня еще наткнулся на любопытный пост:

            А мона ссылку на оригинальный пост ??
              Цитата jack128 @
              А мона ссылку на оригинальный пост ??

              Re: Выгоды контрактного программирования (design by contract) квадратосрач2 +

              Добавлено
              Цитата Повстанець @
              А я вот всё ещё не понял. Так списки совсем динамические, или динамически просто заполняются?

              Что значит "совсем динамические"? Это как списки в CL например?
                тупо в лоб..

                ExpandedWrap disabled
                  type
                    TFirst  = array[0..5] of Integer;
                    TSecond = array[0..6] of Integer;
                    
                  var
                    SP     : Integer;
                    i      : Integer;
                    First  : TFirst;
                    Second : TSecond;
                  begin
                    {$IF LENGTH(First) <> LENGTH(Second)}
                      {$MESSAGE ERROR 'Ошибка!'}
                    {$IFEND}
                   
                    First[0] := 0;
                    First[1] := 1;
                    First[2] := 2;
                    First[3] := 3;
                    First[4] := 4;
                   
                    Second[0] := 0;
                    Second[1] := 1;
                    Second[2] := 2;
                    Second[3] := 3;
                    Second[4] := 4;
                   
                    SP := 0;
                   
                    for i := Low(First) to High(First) do    
                      SP := SP + First[i] * Second[i];
                   
                    Writeln(SP);
                    Readln;
                  end.


                P.S.
                всё это очень похоже на плюсовые ассерты времени компиляции (или как их там?)..

                Добавлено
                Цитата korvin @
                но параметризированные монады позволяют отловить данную ошибку - в момент компиляции.

                Ну а если файл будет открываться/закрываться в виртуальном методе?

                P.S.
                согласен с D_KEY, подходит не для всех случаев (а для большинства тех, что подходит, польза сугубо академическая).
                  Цитата MyNameIsIgor @
                  Гля, вы гениальны! А я и не догадывался! (если кто не понял - это вариация на тему "спасибо, кэп").

                  Тогда в чем вопрос?

                  Цитата MyNameIsIgor @
                  Давайте серьёзно, а? А то второй раз меня забанят...

                  Так будь серьёзен, тогда не забанят.

                  Цитата MyNameIsIgor @
                  Вы же прекрасно поняли, что длина подобного списка вводится пользователем.

                  Какого "подобного"? Я предоставил два несимметричных списка. Если тебе нужны списка, полученных из разных значений m и n, введенных пользователем, то естественно компилятор не может гарантировать, что они будут равны. И никакой компилятор никакого языка никогда не сможет этого сделать. Максимум, что он может -- потребовать проверку в сомнительных случаях и уже после проверки считать, что равенство/неравенство длин доказано.

                  (Хаскельный) компилятор в общем случае не может даже доказать, что результаты f и g будут иметь одинаковый тип в следующем коде:
                  ExpandedWrap disabled
                    test2 :: Integer -> Integer
                    test2 n = scalarProduct (f n 0 Nil) (g n 0 Nil) where
                        f :: ScalarProduct a => Integer -> Integer -> a -> a
                        f 0 _ xs = xs
                        f m i xs = f (m-1) (i+1) (Cons (2*i+1) xs)
                        g :: ScalarProduct a => Integer -> Integer -> a -> a
                        g 0 _ xs = xs
                        g m i xs = f (m-1) (i+1) (Cons (i^2) xs)

                  потому что (в Хаскелле) типы нельзя параметризовать рантайм-переменными, т.е. он не знает, что типы результатов f и g зависят только от m и при одинаковых m (а в данном случае они одинаковы, т.к. в них передается значение одной и той же переменной n) будут одинаковы, т.е. списки будут иметь равные длины.

                  Добавлено
                  Цитата DesweR @
                  Ну а если файл будет открываться/закрываться в виртуальном методе?

                  О каких виртуальных методах в Хаскеле идет речь? И вообще о чем, я что-то не понял.

                  Цитата DesweR @
                  согласен с D_KEY, подходит не для всех случаев (а для большинства тех, что подходит, польза сугубо академическая).

                  Ты просто тоже не понял, о чем пример. Еще раз для всех: основной смысл примера не в том, чтобы знать какая длина у списка на этапе компиляции, это в общем случае невозможно, а в том, чтобы гарантировать для функции, обрабатывающей два списка (в примере -- scalarProduct), что она не получит два списка разной длины и гарантировать это на этапе компиляции.

                  Добавлено
                  Цитата DesweR @
                  тупо в лоб..

                  ExpandedWrap disabled
                    type
                      TFirst  = array[0..5] of Integer;
                      TSecond = array[0..6] of Integer;
                      ...

                  А теперь то же самое, только чтоб длина задавалась в рантайме, ок?
                    Цитата korvin @
                    О каких виртуальных методах в Хаскеле идет речь? И вообще о чем, я что-то не понял.

                    Это мы не поняли, тут речь о C++/C#/Java/Delphi ;)

                    Цитата korvin @
                    А теперь то же самое, только чтоб длина задавалась в рантайме, ок?

                    Не :no:
                    Сообщение отредактировано: DesweR -
                      Цитата korvin @
                      А теперь то же самое, только чтоб длина задавалась в рантайме, ок?

                      Эмм, а где в коде на Хаскелле задание длины списка в рантайме? :huh:
                        Т.е. смотрите:
                        ExpandedWrap disabled
                          test' :: ScalarProduct a => Integer -> Integer -> a -> a -> Integer
                          test' 0 _ xs ys = scalarProduct xs ys

                        a == a, т.е. типы xs и ys будут гарантировано одинаковы, именно это и разрешает применение scalarProduct к ним (она тоже требует одинаковые типы), а, поскольку, собственно функция вычисляется в рантайме, то и длина может быть задана в рантайме.

                        Да, судя по всему в этом случае тип a неизвестен на этапе компиляции, поэтому он будет строиться в динамике, как и диспетчеризация scalarProduct (выбор реализации между типами Cons и Nil) будет соответственно происходить в рантайме, хотя раньше я думал, что диспетчеризация тайпклассовых функций происходит только в компайл-тайме.

                        Добавлено
                        Цитата Мяут-Настоящий @
                        Эмм, а где в коде на Хаскелле задание длины списка в рантайме? :huh:

                        ExpandedWrap disabled
                          ...
                           
                          test :: Integer -> Integer
                          test n = test' n 0 Nil Nil where
                              test' :: ScalarProduct a => Integer -> Integer -> a -> a -> Integer
                              test' 0 _ xs ys = scalarProduct (lmap fx xs) (lmap fy ys)
                              test' n i xs ys = test' (n-1) (i+1) (Cons i xs) (Cons i ys)
                           
                          main :: IO ()
                          main = print . test . read . head =<< getArgs

                        Длина берется из первого аргумента, переданного программе:
                        ExpandedWrap disabled
                          D:\usr\Development\haskell> ghc -o test test.hs
                          [1 of 1] Compiling Main             ( test.hs, test.o )
                          Linking test.exe ...
                           
                          D:\usr\Development\haskell> test 1
                          0
                           
                          D:\usr\Development\haskell> test 4
                          86
                           
                          D:\usr\Development\haskell> test 15
                          23065
                           
                          D:\usr\Development\haskell>


                        Добавлено
                        Цитата DesweR @
                        Это мы не поняли, тут речь о C++/C#/Java/Delphi ;)

                        Поэтому я ту цитату поместил в спойлер, чтобы не мозолила глаза, а кого-нибудь оно могло и заинтересовать.
                          Цитата korvin @
                          И никакой компилятор никакого языка никогда не сможет этого сделать.

                          О том и речь. Что не может. А от приведенных примеров толку немного.
                          Но если смотреть на задачу, как на теоретическую, то да, в С++ для формирования таких списков в рантайме придется отказаться на определенном этапе от рекурсивного шаблонного типа(как собственно и происходит с дженериками на автомате), потому код будет не столь наглядным.

                          Цитата
                          Максимум, что он может -- потребовать проверку в сомнительных случаях и уже после проверки считать, что равенство/неравенство длин доказано.

                          Разве он это будет делать посредством типизации?

                          Цитата
                          Ты просто тоже не понял, о чем пример. Еще раз для всех: основной смысл примера не в том, чтобы знать какая длина у списка на этапе компиляции, это в общем случае невозможно, а в том, чтобы гарантировать для функции, обрабатывающей два списка (в примере -- scalarProduct), что она не получит два списка разной длины и гарантировать это на этапе компиляции.
                          Это было понятно(см. выше я где-то это же самое говорил кому-то).
                          Но профит тут исключительно теоретический. На практике гораздо надежнее/проще/полезнее будет как-нибудь так:
                          ExpandedWrap disabled
                            int n;
                            std::cin >> n;
                            std::vector<int> v1(n), v2(n);

                          И даже ошибиться в таком коде гораздо сложнее ;)

                          Добавлено
                          Цитата Мяут-Настоящий @
                          Цитата korvin @
                          А теперь то же самое, только чтоб длина задавалась в рантайме, ок?

                          Эмм, а где в коде на Хаскелле задание длины списка в рантайме? :huh:

                          Ну как же, функция main' же в том коде принимает n.
                          На самом деле просто превосходный пример, демонстрирующий разницу между шаблонами и полиморфными типами/дженериками.
                            Цитата D_KEY @
                            Разве он это будет делать посредством типизации?

                            С их помощью.
                              Цитата korvin @
                              Да, судя по всему в этом случае тип a неизвестен на этапе компиляции, поэтому он будет строиться в динамике, как и диспетчеризация scalarProduct (выбор реализации между типами Cons и Nil) будет соответственно происходить в рантайме, хотя раньше я думал, что диспетчеризация тайпклассовых функций происходит только в компайл-тайме.

                              Нет, не будет тип строиться на этапе выполнения. Это не требуется. Компилятор итак знает, что типы будут корректны - ему достаточно рассмотреть "текущую" итерацию, если в ней типы корректны, значит будут корректны и в следующей.

                              Добавлено
                              Собственно, С++ шаблоны напрямую не работают как раз потому, что они не являются (полиморфными) типами - они именно шаблоны, по которым генерируются конкретные не параметризованные типы.
                              Сообщение отредактировано: D_KEY -
                                Цитата D_KEY @
                                Это было понятно(см. выше я где-то это же самое говорил кому-то).
                                Но профит тут исключительно теоретический.

                                Это все равно, что заявлять, что от статической типизации профит исключительно теоретический. Или, что от вывода типов профит исключительно теоретический. Или от шаблонов/дженериков. Или от контрактов.

                                Цитата D_KEY @
                                На практике гораздо надежнее/проще/полезнее будет как-нибудь так:
                                ExpandedWrap disabled
                                  int n;
                                  std::cin >> n;
                                  std::vector<int> v1(n), v2(n);

                                И даже ошибиться в таком коде гораздо сложнее ;)

                                В каком месте тут надежней/проще/полезней и даже ошибиться гораздо сложнее?

                                И собственно, чем это отличается от хаскеллного кода? Как теперь будет выглядеть функция scalarProduct для vector<int>?

                                Добавлено
                                Цитата D_KEY @
                                Нет, не будет тип строиться на этапе выполнения. Это не требуется. Компилятор итак знает, что типы будут корректны - ему достаточно рассмотреть "текущую" итерацию, если в ней типы корректны, значит будут корректны и в следующей.

                                Будет. Потому что инстансы тайпклассов диспетчеризуются по типам, для того, чтобы на каждой "итерации" правильно выбирать реализацию scalarProduct, тип списка должен построиться полностью. Для тайпчека это не требуется, да.
                                2 пользователей читают эту тему (2 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (495) « Первая ... 424 425 [426] 427 428 ...  494 495


                                Рейтинг@Mail.ru
                                [ Script execution time: 0.5676 ]   [ 14 queries used ]   [ Generated: 29.07.26, 17:43 GMT ]