Някакъв начин за добавяне на шаблони, тип подпис към функция в GHCi?

^-- Не, не е съвсем. Въпросът ми обхваща ДОБАВЯНЕТО на шаблони и подписи за въвеждане интерактивно...което очевидно е невъзможно.

Най-основните неща, които можете да опитате да направите от ранните уроци, няма да работят в GHCi:

foo [] = []
foo (x:xs) = x : foo xs

Това работи, ако го поставите в foo.hs и в подканата GHCi въведете :load foo.hs. След това можете да извикате foo в списък и да върнете списъка обратно.

Ранните търсения в Google ви казват, че в GHCi имате нужда от let изявление. Но в този случай (функция, дефинирана с множество шаблони) няма да работи:

Prelude> let foo [] = []
Prelude> let foo (x:xs) = x : foo xs
Prelude> foo [1, 2, 3]
[1,2,3*** Exception: <interactive>:3:5-27: Non-exhaustive patterns 
    in function foo

Второто "нека" замени първото "нека". Изоставянето на let не е опция. И не му харесва, ако въвеждате изрази като foo :: [a] -> [a].

Уроците изглежда заобикалят това и ви изпращат бързо да поставите кода си във файлове. Ами ако не искате да правите файл и искате да работите интерактивно? Какви са вариантите?


person HostileFork says dont trust SE    schedule 27.07.2014    source източник
comment
възможен дубликат на Как да дефинирам функция в ghci в множество линии?   -  person Ionuț G. Stan    schedule 27.07.2014
comment
възможен дубликат на многоредови команди в GHCi   -  person Sibi    schedule 27.07.2014
comment
@IonuțG.Stan Чел съм това. Това не е същият въпрос. И знанието, че изразът let ще се групира с всичко след него, е много специфична странност. Така че по принцип, ако имам файл, пълен с дефиниции от урок, казвам нека веднъж и няма значение какво е последващото съдържание?   -  person HostileFork says dont trust SE    schedule 27.07.2014


Отговори (2)


Не. Не можете да добавяте нови модели или сигнатура на тип към функция в GHCi, след като сте изпълнили израз, който я дефинира в оценителя.

По този въпрос, вие също не трябва да го виждате като "добавяне" на база ред по ред в изходния код. Това е просто удобство при записване. Така че, когато погледнете "многоредова" дефиниция като:

foo :: [a] -> [a]
foo [] = []
foo (x:xs) = x : foo xs

Всички тези дефиниции на foo трябва да бъдат свързани заедно като група. Не можете да ги разделите... така че например това ще доведе до грешка:

foo :: [a] -> [a]
foo [] = []

bar = 3

foo (x:xs) = x : foo xs

(Забележка: Сигнатурата на типа може да бъде разделена обаче. За подробности относно това доколко може да бъде разделена, вижте Как се дефинира грануларността „блок" в Haskell? )

За да съберете нещата като група, можете да използвате многоредов вход в GHCi. Или можете да направите всичко на един ред с точка и запетая:

let foo :: [a] -> [a] ; foo [] = [] ; foo (x:xs) = x : xs

Но не можете да въведете вход, да го тествате, след това да закърпите отделни шаблони навътре и навън и да го тествате отново. Цялата функция се предефинира с всяко let.

person HostileFork says dont trust SE    schedule 27.07.2014

Използвайте многоредов вход:

Prelude> :set +m
Prelude> let
Prelude| foo [] = []
Prelude| foo (x:xs) = x : foo xs
Prelude| 
Prelude> foo [1,2,3]
[1,2,3]
person vivian    schedule 27.07.2014
comment
Няма ли начин да посочите N шаблона, да опитате, да получите проблем и да го коригирате без многоредов вход, указващ отново всички шаблони? - person HostileFork says dont trust SE; 27.07.2014
comment
@HostileFork, не в момента. Има предложение, че целият многоредов вход може да бъде възстановен от хронологията на въвеждането, но все още не е приложен. - person vivian; 27.07.2014
comment
Хм. Изглежда, че не могат да се разделят моделите за foo с разпръсната друга дефиниция (като foo [] = [] последвано от bar = 3 и след това foo (x:xs) = x : foo xs) Така че дори ако ги въвеждате в източник, те ефективно се дефинират всички в незабавно... така че дори там няма ред по ред. Правилно? - person HostileFork says dont trust SE; 27.07.2014
comment
@HostileFork Всички уравнения за една функция/променлива трябва да са последователни, както във файл. И всичко от let до празния ред се анализира наведнъж, като let блок. (GHCi е снизходителен, като не изисква допълнителен отстъп за блоковите елементи в този случай.) - person Ørjan Johansen; 27.07.2014
comment
@HostileFork BTW в GHCi (и lambdabot) имам склонност да използвам изрични ; и много случайни {} скоби (не толкова често необходими, колкото си мислите) вместо многоредови. Предимно стар навик, но това има предимството, че обикновено мога да редактирам отново целия ред наведнъж. - person Ørjan Johansen; 27.07.2014
comment
@ØrjanJohansen Благодаря... вижте опита ми да отговоря на собствения си въпрос. Някакъв нюанс, който искате да добавите? Изглежда, че сигнатурата на типа може да бъде отделена от дефинициите на функцията, но не можете да направите независимо един подпис на сигнатура на тип, който мога да кажа... - person HostileFork says dont trust SE; 27.07.2014
comment
@HostileFork Наистина не се изисква сигнатурата на типа да е последователна с уравненията, но трябва да е в същия блок. - person Ørjan Johansen; 27.07.2014
comment
@ØrjanJohansen Има ли формална дефиниция на блок Haskell, подходящ за това? Виждам, че се споменава do-block, но ако използвате изходни файлове, тогава каква е детайлността на блок? - person HostileFork says dont trust SE; 27.07.2014
comment
@HostileFork Любопитно е, че докладът на Haskell почти не използва термина блок, говорейки за оформление вместо това. Има четири стандартни вида, where, let, do и (case) of блокове. Първите две са тези, които могат да имат декларации на функции и други подобни. Целият изходен файл е технически незадължителна декларация на модул, последвана от един вид where блок. - person Ørjan Johansen; 27.07.2014
comment
@ØrjanJohansen Достатъчно интересна точка за нов въпрос, мисля.. . - person HostileFork says dont trust SE; 27.07.2014