LINUX.ORG.RU

Помогите разобраться в haskell

 


0

2

В общем пытаюсь примеры в интерпретаторе набирать из книжки с github'а:

data Bool = True | False

true :: Bool
true = True

false:: Bool
false = False

Пытаюсь скормить это интерпретатору:

*Main> data Bool = True | False
*Main> true :: Bool

<interactive>:5:1: Not in scope: `true'

Кстати, может редактор-ide посоветуете чисто для haskell'а?
Emacs и Vim прошу не предлагать(Пользовался Emacs, бросил... Vim просто не нравится). Сейчас kate использую.

★★★★★

true :: Bool

Вот это не надо кормить интерпретатору.

И, да, лучше всё таки в файле писать и потом :l его

yoghurt ★★★★★
()

в интерпретаторе там надо вводить что-то типа
let true = True //хотя может брежу и этот let там для чего-то другого.

Bad_ptr ★★★★★
()
Последнее исправление: Bad_ptr (всего исправлений: 1)

Лучше делать отдельный файлик, и грузить его по :l (:load), а потом и по :r (:reload) в ghci. Т.е. поредактировал файлик, написал :r в ghci, опять подредактировал файлик. В твоем случае файлик должен начинаться с

module Main where

Ну и команды :info, :type и :kind никто не отменял.

Интерпретатор все правильно ругается, ведь true ты забыл определить. В ghci это делается через

let true = True
. Вообще-то, Bool уже определен в Prelude и его переопределение ни к чему хорошему кроме феерических сообщений ошибках не приведет.

Macil ★★★★★
()
Ответ на: комментарий от deterok

Что значит ":" ? Команд интерпретатору?

Да. Почитай документацию по GHC. Все подробно описано.

Macil ★★★★★
()
Ответ на: комментарий от deterok

почему в книге не написано про let?

Потому что есть невысказанный консенсус, что GHCi - беспомощное говно, годное только для однострочников. Более-менее сложный код подгружается через :l

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от deterok

Я понимаю, но почему в книге не написано про let?

Потому что всем пофиг на let. И делают именно так как тебе написали: грузят в интерпретатор файлики.

Кстати говоря, ghci в этом плане достаточно умный, и по :reload будет перезагружать только изменившиеся модули.

Macil ★★★★★
()

*Main> true :: Bool

Так не получится, вводи в редакторе и скармливай через :l

encyrtid ★★★★★
()
Ответ на: комментарий от Macil

Что я делаю не так:

module Main where

data Bool = True | False
let true :: Bool

ghci test.hs

[1 of 1] Compiling Main             ( test.hs, interpreted )

test.hs:4:17:
    parse error (possibly incorrect indentation or mismatched brackets)
Failed, modules loaded: none.

Хочу сразу предупредить, что я только первые примеры стал забивать из книжки и просто еще не понимаю до конца, что происходит.

deterok ★★★★★
() автор топика
Ответ на: комментарий от Macil

Убрал let, получил

test.hs:4:1:
    The type signature for `true' lacks an accompanying binding

test.hs:4:9:
    Ambiguous occurrence `Bool'
    It could refer to either `Main.Bool', defined at test.hs:3:6
                          or `Prelude.Bool',
                             imported from `Prelude' at test.hs:1:8-11
                             (and originally defined in `GHC.Types')

deterok ★★★★★
() автор топика
Ответ на: комментарий от deterok

А что такое deriving (Eq, Show)?

Магическое выражение. Без него не очень удобно пользоваться полученным дататипом. Не бери в голову.

Macil ★★★★★
()
Ответ на: комментарий от Macil

Хорошее начало, двоякий синтаксис и магические выражения.
Я в общем понимаю, что это для сравнения и отобрания, но не понимаю как оно подцепится.

deterok ★★★★★
() автор топика
Ответ на: комментарий от deterok

Хорошее начало, двоякий синтаксис и магические выражения

В любом естественном языке есть такие магические выражения... Называются языковыми клише. На начальном уровне обучения заучиваются целиком. Без понимания, по каким правилам они строятся. Говорю же: не бери в голову.

но не понимаю как оно подцепится

Я тоже не понимаю, не переживай.

Macil ★★★★★
()
Ответ на: комментарий от Macil

let таким образом используется только в ghci. В хаскеле у let другой синтаксис.

Нифига подобного. Надо просто учитывать, что весь код введённый в ghci выполняется внутри do-блока.

hateyoufeel ★★★★★
()
Ответ на: комментарий от deterok

А что такое deriving (Eq, Show)?

Автоматическое инстанцирование указанных тайпклассов (с дефолтными реализациями методов).

hateyoufeel ★★★★★
()

1) У ghc и ghci несколько разный принцип работы. Ghc видит файл целиком, засасывает его полностью и позволяет использовать значения, определённые позднее. Например:

n :: Integer
n = m + 1

m :: Integer
m = 2

ghci так делать не может. Поэтому в нём синтаксис несколько другой. Приближённо можно считать, что всё, что делается в ghci, завёрнуто в один большой do-блок в монаде IO. Отсюда и let в определениях переменных.

2) deriving (Eq, Ord).

Почитай про классы типов. Там ты узнаешь, что есть, среди прочего, классы Eq и Ord. Они - встроенные, компилятор о них знает, и потому может написать правильные реализации сам. Ты можешь их написать руками, примерно так:

instance Eq Bool where
  T == T = True
  T == _ = False
  F == F = True
  F == _ = False
instance Ord Bool where
  compare F F = EQ
  compare F _ = LT
  compare _ F = GT
  compare T T = EQ

но ghc готов сделать это за тебя.

3) Учти, что в стандартной библиотеке уже определён тип Bool, и если ты назовёшь свой тип также, то при использовании будет путаница.

Miguel ★★★★★
()
Ответ на: комментарий от deterok

В случае с c++ наиболее близким к type class термином будет полностью абстрактный класс, но есть различия.

hateyoufeel ★★★★★
()
Ответ на: комментарий от deterok

А можно расшифровать для ++/Питониста?

Не беги впереди паровоза и не старайся понять все и сразу. Сначала нужно хотя бы то тайпклассов дойти.

Macil ★★★★★
()
Последнее исправление: Macil (всего исправлений: 1)
Ответ на: комментарий от deterok

Я понимаю, но почему в книге не написано про let?

Читай лучше RWH

yoghurt ★★★★★
()
Ответ на: комментарий от deterok

Это значит, что объявленный тип данных автоматом получает методы проверки на равенство и преобразование в строку (типа equals() и toString()).

ovk48 ★★★
()

1. Выкинь книжку

2.

ghci -XNoImplicitPrelude
λ> :{
| data Bool = True | False
| :}
λ> let true = True
λ> let false = False
λ> :t true
true :: Bool

так хочется?

3. emacs/vim.

qnikst ★★★★★
()
Ответ на: комментарий от tailgunner

странный консенсус, но действительно логичнее через :l, т.к. текущий «state» в файл загнать нельзя.

qnikst ★★★★★
()
Ответ на: комментарий от deterok

двоякого синтаксиса нет, в ghci всё выполняется в IO монаде, т.е. там ровно тот же сахар, что и в do в обычном коде. То, что в книге это не написано это проблема книги, а не языка.

deriving это механизм автоматического создания инстансов классов, он возможен для базовых классов Eq,Read,Show,Enum.. и с расширениями для некоторых других, Functor, MonadX, Typeable, Generic.

qnikst ★★★★★
()
Ответ на: комментарий от Macil

Чрт, это бесит. Ни один пример из книжки еще не сработал нормально.

module Main where

data MyBool = T | F 

true :: MyBool
true = T

false :: MyBool
false = F

not :: MyBool -> MyBool
not true = false
not false = true

and :: MyBool -> MyBool -> MyBool
and false _ = false
and true  x = x

or :: MyBool -> MyBool -> MyBool
or true  _ = true
or false x = x

xor :: MyBool -> MyBool -> MyBool
xor a b = or (and (not a) b) (and a (not b))
И вот что он кидает:
ghci test.hs
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
[1 of 1] Compiling Main             ( test.hs, interpreted )

test.hs:24:11:
    Ambiguous occurrence `or'
    It could refer to either `Main.or', defined at test.hs:20:1
                          or `Prelude.or',
                             imported from `Prelude' at test.hs:1:8-11
                             (and originally defined in `GHC.List')

test.hs:24:15:
    Ambiguous occurrence `and'
    It could refer to either `Main.and', defined at test.hs:16:1
                          or `Prelude.and',
                             imported from `Prelude' at test.hs:1:8-11
                             (and originally defined in `GHC.List')

test.hs:24:20:
    Ambiguous occurrence `not'
    It could refer to either `Main.not', defined at test.hs:12:1
                          or `Prelude.not',
                             imported from `Prelude' at test.hs:1:8-11
                             (and originally defined in `GHC.Classes')

test.hs:24:31:
    Ambiguous occurrence `and'
    It could refer to either `Main.and', defined at test.hs:16:1
                          or `Prelude.and',
                             imported from `Prelude' at test.hs:1:8-11
                             (and originally defined in `GHC.List')

test.hs:24:38:
    Ambiguous occurrence `not'
    It could refer to either `Main.not', defined at test.hs:12:1
                          or `Prelude.not',
                             imported from `Prelude' at test.hs:1:8-11
                             (and originally defined in `GHC.Classes')
Failed, modules loaded: none.
Prelude>

Никак нельзя сказать ему, что я хочу именно свои функции тащить?
Мне просто вот интересно почему он меня вообще об этом спрашивает, если я в модуле Main нахожусь? Он сам определил за меня not, or и другие.
Надеюсь, что тяжело в учение, легко в бою...

deterok ★★★★★
() автор топика
Ответ на: комментарий от deterok

ghci test.hs

Выше уже писали:

ghci -XNoImplicitPrelude test.hs

Ну и deriving у Bool таки добавь, а то следующим вопросом будет почему он не печатает нормально результаты :)

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

Или

import Prelude hiding ( not, and, or )

и т.п. сразу после module Main where.

quasimoto ★★★★
()

синтаксис интерпретатора немного отличается от синтаксиса компилятора.

из ide пользовал только leksah и vim, первое на дебиане у меня не работает, так что лучше vim

MyTrooName ★★★★★
()
Ответ на: комментарий от quasimoto

Так вот он с этой директивой ругается, что не может найти show

deterok ★★★★★
() автор топика
Ответ на: комментарий от quasimoto

А откуда он знает заранее что над моим типом логические операции проводить? Дженерики?

deterok ★★★★★
() автор топика
Ответ на: комментарий от deterok

Так вот он с этой директивой ругается, что не может найти show

http://www.haskell.org/onlinereport/modules.html

По стандарту всякий модуль неявно импортирует весь Prelude, чтобы все обычные типы, операции и т.п. сразу были доступны (Bool, Int, (+), Show и т.п.), XNoImplicitPrelude отключает это поведение. Если есть необходимость конфликтовать с одними именами Prelude и использовать другие, то делаем import Prelude нужным образом

import Prelude ( тут явно пишем что импортировать, например — Bool(..), даст Bool, True и False )

import Prelude hiding ( пишем что не импортировать — not, and, or, (&&), (||) )

import qualified Prelude as P — всё остальное вызываем по P.not и т.п.

и т.п.

с конфликтами с именами других модулей так же (например, length и т.п. от разных List, Seq, ByteString, Text, ...).

А откуда он знает заранее что над моим типом логические операции проводить? Дженерики?

Логические ты сам пишешь (зачем-то :)), diriving можно сделать, например, для Read, Show, Eq, Ord, соответственно, это напишет данному типу стандартные функции для чтения, печати, равенства и порядка. Стандартных deriving Boolean нет, хотя в принципе возможно.

quasimoto ★★★★
()
Ответ на: комментарий от deterok

Никак нельзя сказать ему, что я хочу именно свои функции тащить?

Уже ответили, но хинт. Хаскель понимает символ «'» (одинарная кавычка в именах. Т.е. можно называть or'.

Чертовски удобно.

Macil ★★★★★
()

Написал свою первую функцию:)

module Main where

sumAll :: Num a => [a] -> a
sumAll [] = 0
sumAll xs = (head xs) + (sumAll (tail xs))

Понял что такое каррирование и почему оно по сути в ++ не возможно.
Ну в общем стал немного понимать, что происходит вообще :)

deterok ★★★★★
() автор топика
Ответ на: комментарий от yoghurt

Да, дочитал до этого уже, просто к шаблонам привыкнуть никак не могу.

deterok ★★★★★
() автор топика
Ответ на: комментарий от deterok

С таким вариантом

main = print $ sumAll [1 .. 1000000000]

после компиляции с любыми оптимизациями при запуске съест всю кучу.

Вот так

{-# LANGUAGE BangPatterns #-}

sum' :: Num a => [a] -> a
sum' = go 0 where
  go a [] = a
  go !a (x:xs) = go (a + x) xs

или так

import Data.List

sum' :: Num a => [a] -> a
sum' = foldl' (+) 0

будет работать хорошо всегда (от -O0 включительно).

Если без BangPatterns и s/!a/a/ или s/foldl'/foldl/ или s/sum'/sum/ (стандартный sum) — всегда хорошо кроме -O0.

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 2)
Ответ на: комментарий от hateyoufeel

Нифига подобного. Надо просто учитывать, что весь код введённый в ghci выполняется внутри do-блока.

Расскажи теперь, умник, как в обычный do-блок поместить module ... или data ...? Так что «нифига» не «просто», а с оговорками.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.