module Main where

-- Такая запись нагенерит нам не только пользователя, но также и функции для получения значений этих функций
-- Минус здесь в том, что имена такие не могут повторяться в рамках одного модуля


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

data User = User
   { name :: String
   , age :: Int
   } deriving Show


data Pet = Pet 
   { kind :: PetKind
   }

data PetKind = Dog | Cat

-- А еще существуют алиасы!
type Name = String
-- Теперь мы везде можем использовать name

-- А еще есть newtype! Она вводит новый тип с ровно 1 констуктором и ровно 1 полем. И это новый полноценный тип. Но зачем?
newtype OtherName = Name String

-- И еще есть такая штука, как let. Это такой локальный блок кода, с локальной же областью видимости. См. в примере


main = do
    let bob = User "Bob" 30
    print bob

    let s = name bob ++ ", " ++ show (age bob)
    print s

    print (let n = 1
               m = 2
           in n + m + 5)

    -- можно обновлять инстанс
    let newBob = bob { age = age bob + 1 }
    print newBob

    
