Програмиране на Haskell?

Аз съм голям фен, макар че на него съм писал единствено едно хоби-проектче миналата година, което попълва в дадени аритметични изрази тип (3*а+(b/2)^3) случайно-генерирани стойности в променливите, подлежащи на условия (тип a≠b и a+1=2*b) и ги пресмята. Иначе от години го заглеждам и чета, но едва миналата година събрах по-сериозно кураж да го заговоря :D

Страшно поучително упражнение, силно препоръчвам, ако имате време :)
 
Не съм писал, не знам дали някога ще пиша, но често взе да се споменава езика. Главно го срещам да се споменава при Xmonad WM, който е писан на Хаскел и разширенията също се пишат на него.

@Ticketa нещо конкретно ли те интересува или чисто статистически :D
 
Не съм го засичал из проекти. Ама и аз съм малко далеч от това. Или съм с фронт енд или със сървъри нещо. :)
Какво точно е най-доброто му приложение. Нещо може ли да се види изградено с него. Дори и да не е уеб базирано.
 
Не съм писал, не знам дали някога ще пиша, но често взе да се споменава езика. Главно го срещам да се споменава при Xmonad WM, който е писан на Хаскел и разширенията също се пишат на него.

@Ticketa нещо конкретно ли те интересува или чисто статистически :D
Бях чел, че в кардано го ползвали и за това се поинтересувах "статистически" колко се ползва хахахаха :D
 
Въпреки че не го ползвам за работа, мисля, че много си заслужава човек да го умее - защото никой друг (традиционен императивен ООП) език не те учи както haskell на code reuse, isolation & separation of conserns, които ти биват наложени, още докато си пишеш кода, поради самия дизайн на езика. Тези ограничения ти развиват рефакторинг уменията по принцип, което после е полезно при работа с всеки друг език.

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

Когато си минал през език, в който не можеш да напишеш компилираща се програма, която освен бизнес бизнес логика "по между другото" пише и чете от DB или генерира случайни числа от въздуха (а те принуждава да изкараш всичко като явни параметри напр.), си създаваш навици да пишеш разбираем и логически обособен код на всякакви езици. Пък да не говорим за type safety и гаранциите, които получаваш с тези ограничения.
 
code reuse, isolation & separation of conserns, които ти биват наложени, още докато си пишеш кода, поради самия дизайн на езика
Можеш ли да дадеш пример. Интересно ми е как е форсирано в езика.

Иначе едно от нещата, които не ми допадат е синтаксиса. Сравнително объркващ е, ако идваш от друг език.
 
не съм сигурен дали е правилно, но ето един пример за функция, която преобразува списък от числа, като добавя 1 към всяко число в списъка
Код:
addOne :: [Int] -> [Int]
addOne [] = []
addOne (x:xs) = (x+1) : addOne xs
функцията приема списък от цели числа [Int] и връща нов списък от цели числа, в който към всеки елемент е добавено 1.
Например, при изпълнение на addOne [1, 2, 3], ще получим [2, 3, 4].
> addOne [1, 2, 3]
[2,3,4]

> addOne [5, 10, 15, 20]
[6,11,16,21]

> addOne []
[]

а относно за изолация (ако приемем, че имаме два модула) първият има четири математически функции за: add, subtract, divide и multiply

както и извикана библиотека Prelude (иначе ще получиш грешка в терминала)

cat MathFunctions.hs
Код:
module MathFunctions (
    add,
    multiply,
    divide,
    subtract',
    ) where

import Prelude (Int, (+), (-), (*), div)

add :: Int -> Int -> Int
add x y = x + y

multiply :: Int -> Int -> Int
multiply x y = x * y

divide :: Int -> Int -> Int
divide x y = x `div` y

subtract' :: Int -> Int -> Int
subtract' x y = x - y

вторият модул съдържа пък изкарването на резултата с функцията: showResult. Тя използва функциите от модула MathFunctions, за да изчисли резултата на операцията.

UserInterface.hs
Код:
module UserInterface (
    showResult
    ) where

import qualified MathFunctions as Math

showResult :: String -> Int -> Int -> IO ()
showResult operation x y =
    case operation of
        "+" -> print $ Math.add x y
        "*" -> print $ Math.multiply x y
        "/" -> print $ Math.divide x y
        "-" -> print $ Math.subtract' x y
        _   -> putStrLn "Invalid operation"

двата модула са логически изолирани защото UserInterface модула не зависи от "имплементацията" на математическите функции. Крайната програма/приложение би, което ги обединява ще изглежда нещо подобно на:

cat main.hs
Код:
import UserInterface

main :: IO ()
main = do
    let x = 5
        y = 10
        operation = "+"
    showResult operation x y

Код:
$ runhaskell main.hs
15

$ ghc main.hs
$ ./main
15

ако случайно не си добавил модулите в същата директория (или не си ги импортнал правилно или просто не си ги създал ще получиш грешка)
Код:
main.hs:1:1: error:
    Could not find module ‘UserInterface’
    Use -v (or `:set -v` in ghci) to see a list of the files searched for.
  |
1 | import UserInterface
  | ^^^^^^^^^^^^^^^^^^^^

Ако пък например искаш да изполваш под папка например src/ в прокета и в нея под папки..за модулите... в който е главната програма (main.hs) импортирането ще стане така:
Код:
import qualified Src.MathFunctions as Math
import qualified Src.UserInterface as UI


главният файл main.hs ще изглежда така:
Код:
import qualified Src.MathFunctions as Math
import qualified Src.UserInterface as UI

import UserInterface

main :: IO ()
main = do
    let x = 5
        y = 10
        operation = "+"
    UI.showResult operation x y

Код:
$ runhaskell src/main.hs

ЕДИТ: Под src може да добавиш още две папки, MathFunctions и UserInterface, в които да поставиш съответните модули.

примерна структура:
Код:
myproject/
├── bin/
└── src/
    ├── MathFunctions/
    │   └── mathfunctions.hs
    ├── UserInterface/
    │   └── userinterface.hs
    └── main.hs

1683031858979.png
 
Последно редактирано:
За първия ред код да питам - addOne :: [Int] -> [Int]
каква по дяволите е идеята тука?!
 
За първия ред код да питам - addOne :: [Int] -> [Int]
каква по дяволите е идеята тука?!
указва типовете на входа и изход. в Haskell "функционалните сигнатури" показват типа вход и изход, които функцията приема и произвежда.

btw имах грешка в кода:
Код:
addOne :: [Int] -> [Int]
addOne [] = []
addOne (x:xs) = (x+1) : addOne xs

main :: IO ()
main = do
    let inputList = [1,2,3]
    let outputList = addOne inputList
    print outputList

output:
runhaskell test.hs
[2,3,4]
 

Back
Горе