Andrey
если это в репле, то нужны леты (вроде) и многострочный режим. если в модуле - то нет мэйна и принта
Mansur
main = print $ authenticate "S" "H"
Andrey
точна
Mansur
ну можно
main = print (authenticate "S" "H")
Ilya
ты паттерн-матчишь кортеж, а вызываешь как функцию
Ilya
вызывай как функцию от кортежа или паттерн-матчи без кортежа
Andrey
да, и это тожа
Зигохистоморфный
у тебя же в ПМ пара, а ты юзаешь в вызове функцию с 2 аргументами
Зигохистоморфный
))
Mansur
это следующее сообщение об ошибке :)
Ilya
с такими мелочами я работаю так: сначала пишу в файл определение функции, а потом играюсь с ним уже в REPL
Ilya
так что main не нужен
Mansur
добавь функцию main или запускай в репле
Mansur
или назови модуль по-другому
Mansur
ну а теперь ошибка про кортежи
Mansur
вызывается функция :: String -> String -> Bool, а записана :: (a,a) -> Bool
Ilya
$ cat foo.hs
authenticate ("Santa Claus", "Ho Ho Ho!") = True
authenticate (_, _) = False
Ilya
$ ghci foo.hs
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Main ( foo.hs, interpreted )
Ok, modules loaded: Main.
λ> authenticate ("Santa Claus", "Ho Ho Ho!")
True
λ> authenticate ("1", "2")
False
λ>
Ilya
проверяй
Ilya
че ты не так делаешь
Ilya
как всё заработает - выкидывай кортеж и пробуй без него, он тут не нужен
Alexander
напиши какой тип должен быть у authentificate
Mansur
запятую тоже нужно убрать
Alexander
не нужно играть в обезьянку за печатной машинкой
Alexander
и убирать и добавлять случайные синтаксические элементы
Ilya
да, в хаскелле функции применяются как
f a b
Alexander
так только perl-лу научиться можно
Alexander
и то не факт
Ilya
Alexander
как записывается определение функции от нескольких элементов же знаешь?
Alexander
@Masteroid маловероятно, это ж не перл где любой случайный набор символов это валидная программа 😏
Alexander
\o/
Cheese
первый уровень пройден
Cheese
всего в этой игре 3 уровня
Cheese
1. написать программу
Cheese
2. написать свою программу
Cheese
3. выбрать свой путь
Vladislav
Рано или поздно я до (1) доберусь
Vladislav
Пока что только библиотеки выходят, а программы не особо.
Arseniy
Скоро выйдет ;)
Alexander
поздравляю с релизом красивого сайта пока :)
Влод
просто поделюсь: vscode + haskero очень даже неплох. правда мне поначалу казалось что там автодополнение по типу, но видимо просто везло.
и ещё вот такую табличку нашёл https://github.com/rainbyte/haskell-ide-chart
Влод
поидее кейворды в лексере и всякие комы с семиколонами должны иметь тип Parser () в отличие от идентифиеров, имя которых должно дальше пригодится
но в документации и гайдах они Parser String. Даже в диагностике ошибок этот стринг вроде не нужен
или я что-то упускаю?
Cheese
Cheese
@vlastachu, ты всегда можешь игнорировать String
Cheese
а наоборот, возможно, кому-нибудь тоже будет надо когда-нибудь
Cheese
например, различать каждую из сотни юникодных запятых
Anonymous
Cheese
а чего ж не <$>?
например, потому что в классе Functor написано именно fmap
Зигохистоморфный
вообще там do не нужен
Зигохистоморфный
можно и просто fmap
Зигохистоморфный
putStrLn <$> (fmap fn getLine)
Ilya
Да, без do
Alexander
putStrLn =<< fmap fn getLine тогда уж
Alexander
а то получается IO (IO ())
Vasiliy
да тут и fmap не нужен putStrLn . fn =<< getLine
кана
Часто кто использует =<<?
Alexander
часто не знаю, иногда использую
Dmitry
Товарищи, подскажите, существуют ли инструменты для автоматического преобразования формул, чтобы они считались более стабильно, наподобие https://github.com/mikeizbicki/HerbiePlugin, но не в виде плагина к GHC, а как отдельный инструмент? Грубо говоря, у меня есть формула, я хочу её куда-нибудь запихать и получить эквивалентную формулу, но которая будет считаться стабильно.
Dmitry
Мб что-то такое есть в Mathematica, Maple или в качестве малоизвестного плагина к Sympy?
Зигохистоморфный
какая-то балерина https://ballerinalang.org/
Влод
Чёт выглядит слабеньео
Влод
Для бьютифул
Ну может вытеснить го
Misha
а есть какие-нибудь идиоматические способы делать вот татую штуку без тайпклассов:
f :: X x -> R x
f = f1 если x == x1
f = f2 если x == x2
where
f1 :: X x1 -> R x1
f2 :: X x2 -> R x2
можно и тайпклассом, но как-то совершенно не хочется их сюда тянуть, будет
абсолютно искусственно. Есть какие-нибудь современнеы способы решить между f1 и f2
type level, что-нибудь по типу boost в С++, простигоспади
Я нашел какие-то
https://hackage.haskell.org/package/type-level-0.3.0
но совершенно не уверен, что это оно
кана
Какие-нибудь семейства типов, не уверен. Как с функцией связать хз конечно.
Не, тайпфэмили тут не при чем
Vladislav
А X это что, type family?
Misha
Vladislav
Так вот, надо понимать, что в рантайме в таком случае матчить не на что. Будет у тебя, например, X A = Int, а X B = Bool, вот и придет в твою функцию один указатель, а по нему попробуй пойми что — Int или Bool (не говоря уже о невозможности определить, было это A или B, потому что type families не инъективные)
Vladislav
Решается это тем, чтобы добавить GADT и передавать его
Vladislav
data SX x where
SX_A :: SX A
SX_B :: SX B
f :: SX x -> X x -> R x
Vladislav
А там уж можно на SX матчиться и творить что душе угодно в разных ветках кейса
Misha
ну вот я как раз ничего в рантайме не хочу матчить вообще
Misha
там динамически вообще нечего решать
Vladislav
Если ты не хочешь матчить ничего в рантайме, то вызывай f1 или f2 статически и проблема решена, нет?
Misha
конечно, но мне хочется идиому типа "если параметр типа такой, то вызывать f1, иначе f2"
Vladislav
Ну ладно, тогда давай по порядку разбирать
X A = Int
X B = Int
вызвали, передав Int. Будет f1 для A или f2 для B?
Vladislav
А если гарантированно разное, то начать надо с того, чтобы сделать эту type family инъективной (или заменить на data family)
Misha
у меня есть вот такое
data ErrorCaching = NoErrorCaching | TimedCaching NominalDiffTime
type family IOResult_ v (caching :: ErrorCaching)
type instance IOResult_ v NoErrorCaching = Either SomeException v
type instance IOResult_ v (TimedCaching _) = Either (SomeException, UTCTime) v