Dobře, pojďme začít s tím, jak najít podřetězec v řetězci v Haskell.
Haskell je čistě funkcionální programovací jazyk známý svou vysokou úrovní abstrakce a expresivní syntaxe. Jedním z běžných úkolů při práci s řetězci je najít podřetězec ve větším řetězci – to znamená identifikovat přesnou pozici, kde se vyskytuje určitá sekvence znaků.
Pro tento účel můžeme využít dvě vestavěné funkce Haskell: `isPrefixOf` a `tails`. `isPrefixOf` kontroluje, zda je seznam prefixem jiného seznamu, a `tails` generuje všechny koncové části seznamu. K získání indexu prvního výskytu konkrétního prvku použijeme také funkci `elemIndex` z `Data.List`.
Zde je jednoduché řešení problému:
import Data.List findSubstring :: String -> String -> Maybe Int findSubstring substr str = elemIndex True $ map (isPrefixOf substr) (tails str)
Fungování Kodexu
Funkce `findSubstring` přebírá dva argumenty, `substr` a `str`, které reprezentují podřetězec, který hledáme, respektive řetězec, ve kterém hledáme.
- Za prvé, `tails str` generuje všechny možné konce řetězce `str`. Například zadaný řetězec „ahoj“, „ocasy“ vygenerují [“ahoj“, „ahoj“, „llo“, „lo“, „o“, „“].
- Dále `map (isPrefixOf substr)` aplikuje funkci `isPrefixOf substr` na každý prvek seznamu vytvořeného `tails str`. Získáte tak seznam booleovských hodnot, z nichž každá označuje, zda je `substr` prefixem odpovídajícího prvku v původním seznamu.
- Nakonec `elemIndex True` hledá v tomto seznamu booleanů první výskyt `True`, který odpovídá pozici `substr` v `str`, a vrací jej zabalený v datovém typu `Možná`.
Klíčové funkce a knihovny
Data.List je knihovna Haskell nabitá užitečnými funkcemi pro manipulaci se seznamy. Mimo jiné exportuje funkce `isPrefixOf`, `tails` a `elemIndex`, které jsme použili v našem řešení.
Funkce `isPrefixOf` je pro naše řešení obzvláště klíčová. Kontrolou, zda je náš cílový podřetězec prefixem každého dílčího seznamu, v podstatě zkontroluje každou možnou počáteční pozici našeho podřetězce v rámci původního řetězce.
Extrapolace a varianty
Tento jednoduchý přístup lze extrapolovat pro provádění složitějších úkolů, jako je vyhledání všech výskytů podřetězce, nahrazení podřetězce jiným řetězcem nebo rozdělení řetězce na části na základě oddělovače.
Chcete-li například nahradit všechny výskyty podřetězce, můžete použít `intercalate` z Data.List ke spojení částí získaných přerušením původního řetězce na pozicích cílového podřetězce.
Navzdory své inherentní jednoduchosti a expresivitě Haskellův přístup ke zpracování řetězců ukazuje sílu funkcionálního programování při řešení běžných úloh čistým, čitelným a stručným způsobem.