Компьютерный форум
Правила
Вернуться   Компьютерный форум > Форум программистов > Языки программирования > Prolog
Перезагрузить страницу Исследуем язык программирования Mercury
Ответ
 
Опции темы Опции просмотра
  (#1 (permalink)) Старый
xonix xonix вне форума
Member
 
Сообщений: 429
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 16.03.2007
По умолчанию 19.04.2010, 13:10

Продолжаем в этой ветке. Только, пожалуйста, конструктивно (больше кода, меньше слов :-) ).

Цитата:
Помимо исполняемого файла что-нибудь с собой еще надо носить? Есть еще dll, которые необхоидимо брать при переносе на другую машину?
Думаю, нет. Вернее, может есть какие-то магические опции компилятора (там их очень много) но я пока не встретил. Создает просто один .exe-шник, правда не очень маленький (см. ниже). Пробовал запускать программу, скомпиленную на одной машине - на другой. Всё работало безукоризненно.

Цитата:
Сколько весит минимальный исполняемый файл программы на Mercury? )))
Если компилить по дефолту (low-level c), то 2.37 Мб, если с ключем -s hlc.gc (high-level c + garbage collector), то 1.93 Мб. Замечу, что, вроде-бы, во втором случае код получается еще и немного более быстрый. Размер большой, потому что .exe включает mercury-runtime + используемые библиотечные модули.
Т.ч., фактически размер не будет зависеть от размера вашего кода пока ваш код не станет довольно большим. Да, размер debug-варианта .exe весит порядка 10 Мб.
Ответить с цитированием
  (#2 (permalink)) Старый
raydac raydac вне форума
Member
 
Сообщений: 141
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.09.2008
Адрес: Tallinn, Estonia
По умолчанию 19.04.2010, 16:43

я что то покопался на страничке разработчика языка и не нашел никаких success stories внедрения систем на данном языке, есть какие то коммерческие системы? а то нет ссылок и названий.. с 1993 года прошло 17 лет, должно же было что то быть если концепции заложенные в язык - правильные и закрывающие недоработки в том же Прологе
Ответить с цитированием
  (#3 (permalink)) Старый
xonix xonix вне форума
Member
 
Сообщений: 429
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 16.03.2007
По умолчанию 19.04.2010, 16:54

Цитата:
я что то покопался на страничке разработчика языка и не нашел никаких success stories внедрения систем на данном языке, есть какие то коммерческие системы?
Например, тут используют

http://missioncriticalit.com/
см. http://missioncriticalit.com/technology.html

Ну а еще YesLogic

http://www.yeslogic.com/

создали коммерческий инструмент для работы с XML - PrinceXML

http://www.princexml.com/

ну и, конечно, сам компилятор mercury.
Ответить с цитированием
  (#4 (permalink)) Старый
raydac raydac вне форума
Member
 
Сообщений: 141
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 23.09.2008
Адрес: Tallinn, Estonia
По умолчанию 19.04.2010, 17:07

за 17 лет всеравно маловато имхо..
p.s.
у меня на сайте компании тоже написано что пролог юзаем но нигде пока не довелось его подсоединить коммерчески.. если честно
Ответить с цитированием
  (#5 (permalink)) Старый
xonix xonix вне форума
Member
 
Сообщений: 429
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 16.03.2007
По умолчанию 19.04.2010, 20:02

Еще один опыт.

Пишем на Vip-7 такой код.

Код:
class predicates

    make_list : (integer) -> integer*.

clauses
    make_list(0) = [] :- !.
    make_list(N) = [1 | make_list(N-1)].
    
    run():-
        console::init(),
        Q = length(make_list(70000000)),
        write(Q),
        succeed().
Все работает и даже не падает. Замечательно.

Пишем на mercury аналогичный код:

Код:
make_list(N) = (if N = 0 then [] else [1 | make_list(N-1)]).

main -->
    {
     N = 70000000,
     Res = length(make_list(N)):int
    },
    io.print(Res).
Упс. облом.. код падает, не успев запуститься. =( Фактически это может значить только одно - переполнение стека. Но почему?
Однако, если посмотреть внимательно, можно увидеть что рекурсия-то не хвостовая. В самом деле, после вызова функции make_list(N-1) происходит еще формирование результата [1 | make_list(N-1)]. Если заглянуть в результирующий си-код, там обнаруживается:

Код:
#line 22 "tst1.m"
static MR_Word MR_CALL 
tst1__make_list_1_f_0(
#line 22 "tst1.m"
  MR_Integer tst1__N_3)
#line 22 "tst1.m"
{
#line 22 "tst1.m"
  {
#line 22 "tst1.m"
    MR_bool tst1__succeeded = (tst1__N_3 == (MR_Integer) 0);
#line 22 "tst1.m"
    MR_Word tst1__HeadVar__2_2;

#line 22 "tst1.m"
    if (tst1__succeeded)
#line 22 "tst1.m"
      tst1__HeadVar__2_2 = (MR_Word) MR_mkword(MR_mktag(0), MR_mkbody((MR_Integer) 0));
#line 22 "tst1.m"
    else
#line 22 "tst1.m"
      {
#line 22 "tst1.m"
        MR_Integer tst1__V_4_4 = (MR_Integer) 1;
#line 22 "tst1.m"
        MR_Word tst1__V_5_5;
#line 22 "tst1.m"
        MR_Integer tst1__V_6_6;
#line 22 "tst1.m"
        MR_Integer tst1__V_7_7 = (MR_Integer) 1;

#line 22 "tst1.m"
        tst1__V_6_6 = (tst1__N_3 - tst1__V_7_7);
#line 22 "tst1.m"
        {
#line 22 "tst1.m"
          tst1__V_5_5 = tst1__make_list_1_f_0(tst1__V_6_6);
        }
#line 22 "tst1.m"
        {
#line 22 "tst1.m"
          tst1__HeadVar__2_2 = (MR_Word) MR_mkword(MR_mktag(1), MR_new_object(MR_Word, ((MR_Integer) 2 * sizeof(MR_Word)), "[|]"));
#line 22 "tst1.m"
          MR_hl_field(MR_mktag(1), tst1__HeadVar__2_2, 0) = ((MR_Box) (tst1__V_4_4));
#line 22 "tst1.m"
          MR_hl_field(MR_mktag(1), tst1__HeadVar__2_2, 1) = ((MR_Box) (tst1__V_5_5));
#line 22 "tst1.m"
        }
#line 22 "tst1.m"
      }
#line 22 "tst1.m"
    return tst1__HeadVar__2_2;
#line 22 "tst1.m"
  }
#line 22 "tst1.m"
}
То есть, как видим, самая что ни на есть рекурсия. Действительно, функция tst1__make_list_1_f_0 сама себя вызывает на строке

Код:
          tst1__V_5_5 = tst1__make_list_1_f_0(tst1__V_6_6);
А это значит, что стек рано или поздно переполнится и :wall: А хотелось чтоб получился цикл..

Однако, рано расстраиваться, господа из Мельбурна многое предусмотрели. Пробежавшись по документации находим магический ключик компилятора --optimize-constructor-last-call как раз на этот случай. Компилируем, запускаем. Все работает отлично. Можно залезть в си код и убедиться, что получился цикл.

P.S. Параметры затрат времени и памяти не привожу, во избежание. Могу только намекнуть, что меркурий опять показал себя с лучшей стороны.

Ответить с цитированием
Ads.
  (#6 (permalink)) Старый
calabi-yau calabi-yau вне форума
Member
 
Сообщений: 338
Сказал(а) спасибо: 0
Поблагодарили 10 раз(а) в 10 сообщениях
Регистрация: 28.09.2009
По умолчанию 19.04.2010, 21:07

А как у Mercury в сравнении с Хаскелем, интересно, возможна ли type-magic в стиле:
Код:
data Z
data S a

class Add a b c | a b -> c

instance Add Z b b
instance Add a b c => Add (S a) b (S c) 


class Mul a b c | a b -> c

instance (Add a c c', Mul a b c) => Mul a (S b) c'
instance Mul a Z Z


class Factorial  s r | s -> r

instance (Factorial s r, Mul (S s) r r') => Factorial  (S s) r'
instance Factorial  Z (S Z)


class N'Out a where
  n'out :: a -> Int -> Int

instance N'Out Z where
  n'out _ n = n
instance N'Out a => N'Out (S a) where
  n'out _ n = n'out (undefined :: a) $ n + 1


n'out' :: N'Out a => a -> Int
n'out' a = n'out a 0


t :: Factorial (S (S (S Z))) r => r
t = undefined

main = print $ n'out' t
UPD:
Ага, оказывается нет:
Цитата:
An `instance' declaration gives a type for each parameter of the type class. Each of these
types must be either a type with no arguments, or a polymorphic type whose arguments
are all distinct type variables. For example int, list(T) and bintree(K,V) are allowed,
but T, list(int) and bintree(T,T) are not.
UPD2:
И банальный
Код:
:- typeclass monad(M) where
    [
     func return(T) = M(T)
    ].
тоже не переваривает :(, ибо:
Цитата:
Haskell 98 supports constructor classes, Mercury doesn't.
Но язык интересный, да.
Ответить с цитированием
  (#7 (permalink)) Старый
xonix xonix вне форума
Member
 
Сообщений: 429
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 16.03.2007
По умолчанию 19.04.2010, 22:11

Цитата:
А как у Mercury в сравнении с Хаскелем, интересно, возможна ли type-magic в стиле:
А можно немного пояснить, что делает эта прога, а то я хаскель читаю по слогам и со словарём?..
Ответить с цитированием
  (#8 (permalink)) Старый
SergeMukhin SergeMukhin вне форума
Member
 
Сообщений: 260
Сказал(а) спасибо: 0
Поблагодарили 1 раз в 1 сообщении
Регистрация: 22.06.2006
По умолчанию 20.04.2010, 00:59

Цитата:
Еще один опыт.
Цитата:
Однако, если посмотреть внимательно, можно увидеть что рекурсия-то не хвостовая. В самом деле, после вызова функции make_list(N-1) происходит еще формирование результата [1 | make_list(N-1)]. Если заглянуть в результирующий си-код, там обнаруживается:
<<200 строк пропущено>>
по-моему это хороший пример, показывающий, что работать с mercury невозможно без знания C.

Цитата:
Пробежавшись по документации находим магический ключик компилятора
Для VIP не надо никаких опций оказывается! О!


ps
надо хоть немного уважать читателей форума, и форматировать промежуточный вывод компилятора (если считаете, что он интересен), хотя бы убрали бы #line.
Ответить с цитированием
  (#9 (permalink)) Старый
calabi-yau calabi-yau вне форума
Member
 
Сообщений: 338
Сказал(а) спасибо: 0
Поблагодарили 10 раз(а) в 10 сообщениях
Регистрация: 28.09.2009
По умолчанию 20.04.2010, 13:00

Цитата:
А можно немного пояснить, что делает эта прога, а то я хаскель читаю по слогам и со словарём?..
Простейшая арифметика времени компиляции на типах Хаскеля.

Фактически прямая трансляция в пролог:
Код:
class Add a b c | a b -> c

instance Add Z b b
instance Add a b c => Add (S a) b (S c)
--
add([], B, B).
add([_|A], B, [_|C]) :- add(A, B, C).
Код:
class Mul a b c | a b -> c

instance (Add a c c', Mul a b c) => Mul a (S b) c'
instance Mul a Z Z
--
mul(_, [], []).
mul(A, [_|B], C) :- add(A, C0, C), mul(A, B, C0).
Код:
class Factorial  s r | s -> r

instance (Factorial s r, Mul (S s) r r') => Factorial  (S s) r'
instance Factorial  Z (S Z)
--
factorial([], [_]).
factorial([_|S], R) :- factorial(S, R0),  mul([_|S], R0, R), !.
Код:
class N'Out a where
  n'out :: a -> Int -> Int
--
просто length
Нашел интересную особенность - existential typed functions.
[code]:- typ
Код:
 packed ---> some [T] packed(T).

:- func pack(T) = packed.

pack(X) = 'new packed'(X).

:- some [T] func unpack(packed) = T.

unpack(packed(X)) = X.

:- pred test_packed(state::di, state::uo) is det.

test_packed -->
    {
     L = [
          pack(42),
          pack("string"),
          pack([1,2,3,4])
         ]
    },
    write_list(L, ",", pred(X::in,di,uo) is det --> print(unpack(X))).
Не знаю как такое в хаскеле. Можно объявить объемлющий контекст Printable для типа T для доступа к функции print, но это уже не то
Ответить с цитированием
  (#10 (permalink)) Старый
xonix xonix вне форума
Member
 
Сообщений: 429
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 16.03.2007
По умолчанию 23.04.2010, 19:48


А вот как можно решать логическую задачку из сообщения

[quote]Всё-таки классическими прологами такие задачки прикольнее решать:
Код:
:- module logic.

:- interface.

:- import_module io.

:- pred main(io, io).
:- mode main(di, uo) is det.

:- implementation.

:- import_module list, maybe, solutions, int.

:- type lesson ---> lesson(num, lesson_name, lecturer_name).
:- type lesson_name == maybe(lesson_name_t).
:- type lecturer_name == maybe(lecturer_name_t).
:- type num == maybe(int).

:- type lessons == list(lesson).

:- type lesson_name_t ---> eng; phys; chem; biol; lit; math.
:- type lecturer_name_t ---> a; v; s; d; e; f.

:- func unify_maybe(maybe(T), maybe(T)) = maybe(T) is semidet.
unify_maybe(no,yes(T)) = yes(T).
unify_maybe(yes(T),no) = yes(T).
unify_maybe(no, no) = no.
unify_maybe(yes(T), yes(T)) = yes(T).

:- func unify_lesson(lesson, lesson) = lesson is semidet.
unify_lesson(lesson(N0, L0, P0), lesson(N1, L1, P1)) =
  lesson(unify_maybe(N0, N1),
     unify_maybe(L0, L1),
     unify_maybe(P0, P1)).

:- mode select_l(in,out, in, out).
select_l(A0, unify_lesson(A0, A1), [A1|B], B).
select_l(!B, [A|C], [A|D]) :-
        select_l(!B, C, D).

select(A, [A|B], B).
select(B, [A|C], [A|D]) :-
        select(B, C, D).


check(N, L, P) :-
    (P = s:lecturer_name_t -> (member(L, [chem, biol]), N \= 3); true),
    (P = f -> (L \= lit, N \= 2); true),
    (member(P, [a, v]) -> member(L, [eng, phys]); true),
    (N = 4 -> (member(L, [chem, phys, eng]), \+ member(P, [a, v])); true),
    (N = 5 -> member(P, [v, d]); true),
    (N = 6 -> (member(L, [eng, chem, lit]), member(P, [v, s])); true),
    (L = math -> N mod 2 = 0; true),
    (L = biol -> N > 2; true).

check_all([L | LL1], PP, RR, [Lesson | RR2]) :-
    select(P, PP, PP1),
    select_l(lesson(no,yes(L),yes(P)),Lesson, RR, RR1),
    
    Lesson = lesson(yes(N1),yes(L1),yes(P1)),
    
    check(N1, L1, P1),
    check_all(LL1, PP1, RR1,RR2).
check_all([], [], [],[]).


solve(OutRes) :-
    LL = [eng, phys, chem, biol, lit, math],
    PP = [a:lecturer_name_t, v, s, d, e, f],
    InRes = [lesson(yes(1),no,no),lesson(yes(2),no,no),lesson(yes(3),no,no),
           lesson(yes(4),no,no),lesson(yes(5),no,no),lesson(yes(6),no,no)],
    check_all(LL, PP, InRes, OutRes).

main -->
    {
     solutions((pred(Out::out) is nondet :-
           solve(Out)), Res)
     },
    print(Res).
Код:
$ logic.exe
[[lesson(yes(6), yes(eng), yes(v)), lesson(yes(1), yes(phys), yes(a)), lesson(yes(4), yes(chem), yes(s)), 
lesson(yes(3), yes(biol), yes(f)), lesson(yes(5), yes(lit), yes(d)), lesson(yes(2), yes(math), yes(e))]]
Сказывается отсутствие настоящих логических переменных.
Ответить с цитированием
  (#11 (permalink)) Старый
xonix xonix вне форума
Member
 
Сообщений: 429
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 16.03.2007
По умолчанию 23.04.2010, 20:18

Цитата:
<<200 строк пропущено>>
...
ps
надо хоть немного уважать читателей форума, и форматировать промежуточный вывод компилятора (если считаете, что он интересен), хотя бы убрали бы #line.
Специально пересчитал. Только 54 =)

Цитата:
по-моему это хороший пример, показывающий, что работать с mercury невозможно без знания C.

Для VIP не надо никаких опций оказывается! О!
Да это так :-(. Впрочем, не удивительно, что коммерческий продукт более user-friendly.



Ответить с цитированием
  (#12 (permalink)) Старый
Винитарх Винитарх вне форума
Специалист
 
Аватар для Винитарх
 
Сообщений: 7,956
Сказал(а) спасибо: 2
Поблагодарили 303 раз(а) в 303 сообщениях
Регистрация: 01.03.2003
Адрес: Краснодар
По умолчанию 26.04.2010, 22:32

Я прочитал остатки обрезанной и закрытой Гариком темы о "скорости Прологов и о Mercury". Очевидно есть класс задач, на которых Mercury выигрывает у VIP. Следовательно у SWI он выигрывает ещё больше, чем у VIP. Однако просто так (из ничего) выигрыш не появляется. Если где-то есть плюс, то где-то должен быть минус, при прочих равных условиях. И в чём же минус Mercury?

И ещё, интересно, а как на Mercury будут выглядеть вот такие две Пролог-проги, одна с отсечением, другая без оного:
Код:
member(X,[X|_]):-!.
member(X,[_|L]):-member(X,L).
и
Код:
member(X,[X|_]).
member(X,[_|L]):-member(X,L).
Ответить с цитированием
Ads
  (#13 (permalink)) Старый
aag aag вне форума
ушёл... не вернётся)))
 
Сообщений: 3,400
Сказал(а) спасибо: 0
Поблагодарили 82 раз(а) в 82 сообщениях
Регистрация: 29.11.2008
По умолчанию 26.04.2010, 23:12

Цитата:
...а как на Mercury будут выглядеть ...
Код:
member(X,[X|_]).
member(X,[_|L]):-member(X,L).
Или в одну кучу с bound()/free(), но с отсечением :roll:
Ответить с цитированием
  (#14 (permalink)) Старый
xonix xonix вне форума
Member
 
Сообщений: 429
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 16.03.2007
По умолчанию 27.04.2010, 01:14


Привет Винитарх! С выздоровлением (надеюсь). :-)

Цитата:
Если где-то есть плюс, то где-то должен быть минус, при прочих равных условиях. И в чём же минус Mercury?
Думаю, в его академичности, и как следствие - малоразвитость (это еще слабовато сказано) средств разработки. Хотя дебагер есть, но консольный. IDE нету.

Цитата:
И ещё, интересно, а как на Mercury будут выглядеть вот такие две Пролог-проги, одна с отсечением, другая без оного:
Код:
member(X,[X|_]).
member(X,[_|L]):-member(X,L).
Спасибо за интересную поднятую тему. Которая вскрыла одну интересную штуку. А именно, в mercury оба варианта описываются фактически одной формой а именно (2). Обратите внимание на моды предиката member_nondet. Можно конечно изобразить и (1) (см. member_semidet) но, как видим, не нужно. Т.к. компилятор по одинаковому определению (2) может сгенерить и nondet и semidet (это determ в VIP) код.

Код:
:- module memb.

:- interface.

:- import_module io.

:- pred main(io, io).
:- mode main(di, uo) is det.

:- implementation.

:- import_module list, solutions, int.

:- pred member_semidet(T, list(T)).
:- mode member_semidet(in, in) is semidet.
member_semidet(X, [Y|L]) :-
    ( X = Y
    ; member_semidet(X, L)
    ).

:- pred member_nondet(T, list(T)).
:- mode member_nondet(in, in) is semidet.
:- mode member_nondet(out, in) is nondet.
member_nondet(X,[X|_]).
member_nondet(X,[_|L]):-member_nondet(X,L).

:- type yes_no ---> yes; no.

main -->
    {
     ( member_semidet(2, [1,2,3]) ->
       A = yes
     ; A = no
     ),
     ( member_nondet("qqq", ["q", "qq", "bbb"]) ->
       B = yes
     ; B = no
     ),
     ( solutions((pred(Elem::out) is nondet :-
             member(Elem, 0..20),
              Elem mod 7 = 0
             ), Elems) 
     )
    },
    print(A), % yes
    nl,
    print(B), % no
    nl,
    print(Elems), % [0, 7, 14]
    nl
    .
Код:
Vovan@XONIX /D/TEST/mercury
$ memb
yes
no
[0, 7, 14]
Подумал, может и VIP так умеет. Попробовал так:

Код:
class predicates

    member0 : (Elem, Elem*) determ (i, i) nondeterm (o, i).
    
clauses
    member0(X, [X|_]).
    member0(X, [_|L]) :- member0(X, L).
ругается:

Цитата:
error c631: The predicate 'main::member0/2 (i,i)', which is declared as 'determ', is actually 'nondeterm'
Получается в VIP таки надо два отдельных предиката писать - один с !, второй - без.

UPD. На самом деле оба mercury варианта абсолютно идентичны, т.к. можно к member_semidet добавить декларацию

Код:
:- mode member_semidet(out, in) is nondet.
и получим то же самое.
Ответить с цитированием
  (#15 (permalink)) Старый
SergeMukhin SergeMukhin вне форума
Member
 
Сообщений: 260
Сказал(а) спасибо: 0
Поблагодарили 1 раз в 1 сообщении
Регистрация: 22.06.2006
По умолчанию 27.04.2010, 11:49

Цитата:
дебагер есть, но консольный. IDE нету.

Ответить с цитированием
Пользователь сказал cпасибо:
Kolyan (03.11.2016)
Ответ

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Trackbacks are Вкл.
Pingbacks are Вкл.
Refbacks are Выкл.


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Самый крутой язык программирования Garik Мысли вслух 7103 08.08.2016 13:00
Язык программирования Gwai Prolog 8 17.05.2011 13:42
[ANN] [Mercury] Новый блог по mercury xonix Prolog 0 05.04.2011 14:06
Какой язык программирования выбрать St.Ark Вопросы начинающих программистов 30 16.03.2011 18:58
Разрабатываю язык логического программирования. prokopiy Prolog 71 11.08.2010 22:05
Как создать новый язык программирования на С++ Шоколад Вопросы начинающих программистов 6 15.10.2009 22:52
Язык программирования Barsic Blan Форум программистов 1 22.03.2008 10:26
язык программирования Матрикс Форум программистов 1 07.06.2007 19:16
Скрипт или язык программирования GEV_256 Мысли вслух 24 09.01.2006 01:54
Язык программирования Loid Мысли вслух 17 29.05.2005 23:20
Скриптовый язык vs Язык программирования relonar Мысли вслух 4 24.09.2004 02:14



Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Нardforum.ru - компьютерный форум и программирование, форум программистов