LINUX.ORG.RU

как это делается правильно ?

 expression,


1

2
wah :: Int -> IO ()
wah count = do rnds <- sequence $ replicate count $ randomRIO (0, 59)
               time <- getZonedTime
               let times = map (loctime $ zonedTimeToLocalTime time) rnds
               costs <- sequence $ replicate count $ randomRIO (100, 200 :: Int)
               volumes <- sequence $ replicate count $ randomRIO (10, 20)
               let candles = map (\(t, c, v) -> (Tick t c v)) $ zip3 times costs volumes
               let cnd = mconcat candles
               putStrLn $ fromMaybe "Undefined" $ getCandleColor cnd >>= return . show
               putStrLn $ "open is " ++ (show $ candleOpenCost cnd)
  where
(zonedTimeToLocalTime time) rnd}
    loctime :: LocalTime -> Int -> LocalTime
    loctime time rnd = time {localTimeOfDay = tofday (localTimeOfDay time) rnd}
    tofday :: TimeOfDay -> Int -> TimeOfDay
    tofday time rnd = time {todSec = topico rnd}
    topico :: Int -> Pico
    topico val = (toEnum val * (fromInteger $ resolution $ ((toEnum val) :: Pico)))

Собственно что мы тут видим ? функция которая в начале генерирует список случайных чисел и этот список использует для создания списка элементов LocalTime где оригинальная секунда заменена на число из списка. То что делает функция дальше нас не волнует.

Есть такая фишка в хаскеле можно писать

..... = var {something = newvalue}
и это выражение вернет ту же структуру только с подставленным значением в указанное поле. А как подобное сделать для вложенных структур ? сейчас сделано извращение в where блоке, но сдается мне это не правильно.

PS:: особо доставляет функция topico которая «правильно» преобразует Int в Pico умножая его на размерность Pico (простой toEnum возвращает милиардные доли секунды, правильный хаскель такое правильный).

Я ничего не понял, но sequence . replicate это replicateM

anonymous
()

По поводу доступа к полям смотри на пакеты data-accessor и data-accessor-template.

ratatosk
()

простой toEnum возвращает милиардные доли секунды, правильный хаскель такое правильный

Неосилятор же). Что по вашему делает toEnum?

Для конвертации чем не подошел fromIntegral?

anonymous
()
Ответ на: комментарий от s9gf4ult

А что делает toEnum тогда ?

Пронумеровывает (точнее по номеру возвращает значение), и вроде на то «как именно» - полагаться в общем случае не стоит.

anonymous
()

Я тоже не понимаю, но map (\(a, b, c) -> ...) $ zip3 as bs cs — это zipWith3 (\a b c -> ...) as bs cs.

Miguel ★★★★★
()

А как подобное сделать для вложенных структур ?

var {accessor1 = (accessor1 var) {accessor2 = newvalue}}

например:

data A = A { a_ :: B }
data B = B { b_ :: Int }

test :: A -> A
test a = a {a_ = (a_ a) {b_ = 5}}
quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

не сильно отличается от моего варианта ибо если вложенность более 2 то

data A = A { a_ :: B }
data B = B { b_ :: Int }
data C = C { c_ :: A }

test c = c {c_ = (c_ c) {a_ = (a_ $ c_ c) {b_ = 10}}}

Это же страшно !

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

Можно настроить схему агрегации/подтипов:

{-# LANGUAGE MultiParamTypeClasses, TypeOperators #-}

-- | x in y, y aggregate x, y is a subtype of x, x is a supertype of x.
class x :> y where
  -- | Get a subtype.
  sub :: x -> y
  -- | Get a supertype.
  sup :: y -> x
  -- | Apply to subtype.
  ($>) :: (y -> z) -> x -> z
  ($>) f = f . sub
  -- | Apply to supertype.
  (<$) :: (x -> z) -> y -> z
  (<$) f = f . sup
  -- | Apply inside subtype.
  (>$>) :: (y -> y) -> x -> x
  (>$>) f = sup . f . sub
  -- | Apply inside supertype.
  (<$<) :: (x -> x) -> y -> y
  (<$<) f = sub . f . sup

data A = A { a :: Int } deriving Show
data B = B { b :: A } deriving Show
data C = C { c :: B } deriving Show

-- * Boilerplate instances:

instance Int :> A where { sub = A; sup = a; }
instance A :> B where { sub = B; sup = b; }
instance B :> C where { sub = C; sup = c }
instance Int :> B where { sub = sub . (sub :: Int -> A); sup = sup . (sup :: B -> A); }
instance Int :> C where { sub = sub . (sub :: Int -> B); sup = sup . (sup :: C -> B); }
instance A :> C where { sub = sub . (sub :: A -> B); sup = sup . (sup :: C -> B); }
-- etc.

и делать так:

> let addOne = (+ 1) :: Int -> Int
> addOne <$ A 0
1
> addOne <$< A 0
A {a = 1}
> addOne <$< B (A 0)
B {b = A {a = 1}}
> addOne <$< C (B (A 0))
C {c = B {b = A {a = 1}}}
> let test q = q {c = (sup q) {b = (sup q) {a = 10}}}
> test (C (B (A 0)))
C {c = B {b = A {a = 10}}}

Конечно, каждый раз писать инстансы неудобно - им бы рефлексивность c транзитивностью настроить и с помощью TH генерировать.

Вообще, есть готовые пакеты на эту тему - data-accessor, lenses, fclabels. Они умеют генерировать нужный код с помощью TH. Например, в fclabels будет так:

{-# LANGUAGE TemplateHaskell #-}

import Prelude hiding ( (.) )
import Control.Category ( (.) )
import Data.Label

data A = A { _a :: Int } deriving Show
data B = B { _b :: A } deriving Show
data C = C { _c :: B } deriving Show
$(mkLabels [''A, ''B, ''C])
> get (a . b . c) (C (B (A 10)))
10
> set (a . b . c) 10 (C (B (A 0)))
C {_c = B {_b = A {_a = 10}}}
quasimoto ★★★★
()
Ответ на: комментарий от s9gf4ult

Ещё ссылки по теме: 1, 2, 3 (такие же вопросы на SO), 4 (упрощённое описание линзо-подобных конструкций), 5 (не то, но интересно, про то как аппликативными функторами можно выбирать из подтипа супертип), 6 (F#, SO), 7 (OCaml, SO), 8 (Scala, SO), 9 (Scala, YouTube), 10 (Clojure, InfoQ, философично), 11 (публикации Пирса на тему линз), 12 (категорная модель), 13 (pdf, слайды про библиотеку lenses).

Три последних особенно примечательны - сколько всего интересного можно (нужно) узнать, чтобы написать аналог идиоматичного и банального

    some_struct.some_substruct.some_field = new_value_aight;

Аналогично, столько всего интересного вместо скучного

some_type some_var = some_initial_value;

...

    some_var = new_value;
quasimoto ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.