111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 411
Записей в блоге: 1
1

Как сделать чтобы монада Writer ничего не делала

04.12.2014, 14:05. Показов 1088. Ответов 9
Метки нет (Все метки)

Добрый день, уважаемые.

Зашел в тупик:
Есть такой код (проблемная строка - последняя, но привел целиком, хотя и прорядил немного).
Он переводит траекторию, заданную линиями и дугами, в команды ЧПУ (станок с компьютерным управлением). Все команды предварительно записываются во Writer и уже потом, оттуда в текстовый файл).
функцию g0 привел для примера: g1, g2, g3 - по такому же принципу.

Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
data TSegment = 
        --прямой отрезок
        TLine Double Double
        -- дуга (x, y центра, радиус, угол начала, угол конца, направление)
    |   TArc Double Double Double Double Double Direction 
        --прерывание траектории, при это фреза должна подняться на указанную высоту и уехать на другое место
    |   TJump Double
    deriving (Show)
 
type Trajectory = [TSegment]
 
type CNC = Writer [Command] Command
 
data Position = X Double | Y Double | Z Double
--команды ЧПУ
data Command =G0 [Position] | G1 [Position] | G2 [Position] | G3 [Position] | F Double | Null
write f = writer (aa, [aa]) where aa = f
--быстрое перемещение
g0 :: [Position] -> CNC
g0 l = write $ G0 l
 
--переводим траектория в G-код
trajectory2GCode :: Trajectory -> Double -> CNC
trajectory2GCode (TLine x y : xs) z = do
    g1 [X x, Y y]
    trajectory2GCode xs z
 
trajectory2GCode (TArc x y r a1 a2 CW : xs) z = do --дуга по часовой
    g2 [X x, Y y, I 1, J 2]
    trajectory2GCode xs z
 
trajectory2GCode (TArc x y r a1 a2 CCW : xs) z = do --дуга против часовой
    g3 [X x, Y y, I 3, J 4]
    trajectory2GCode xs z
 
trajectory2GCode (TJump safeZ: xs) z = do --прыжок в другое место
    g0 [Z safeZ]
    g0 [X sx, Y sx]
    g1 [Z z]
    trajectory2GCode xs z
    where 
        (sx, sy) = getFirstPosition xs
 
trajectory2GCode [] _ = write $ Null --закончился список
Смущает последняя строка. Мне нужно просто ничего не делать, но не получается: ни return, ни () - не работает.
Как это правильно сделать?

Спасибо.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
04.12.2014, 14:05
Ответы с готовыми решениями:

Монада. Как лучше сделать программу, выборочно копирующую файлы?
доброго времени суток. вопрос.1. -недавно создавал тему "Haskell - кто может писать на Haskel" в...

Как сделать чтобы программа делала клик мыши?
Как сделать чтобы программа делала клик мыши? То есть программа, словно юзер, наводит курсор на...

Как сделать чтобы в mainmenu при нажатии на определенный подпункт делала видимой Panel
Как сделать чтобы в mainmenu при нажатии на определенный подпункт делала видимой Panel? Например...

Как сделать так чтобы не вылетала ошибка программы когда я ничего не выбрала в lookupcombobox?
когда я нажимаю на список и вдруг передумала что-то выбирать, то я жму на свободное место в...

9
4772 / 2233 / 283
Регистрация: 01.03.2013
Сообщений: 5,873
Записей в блоге: 25
04.12.2014, 14:23 2
Цитата Сообщение от aaleksander Посмотреть сообщение
Мне нужно просто ничего не делать
Буквально вчера столкнулся с той же проблемой. Совершенно не знаю и не понимаю монад, но те пару раз, когда я с ними связывался, вроде помогало
Haskell
1
return ()
- Разложение числа на сумму минимального количества точных кубов
0
650 / 260 / 16
Регистрация: 02.03.2014
Сообщений: 587
04.12.2014, 14:43 3
А записать пустой список не получиться?
1
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 411
Записей в блоге: 1
04.12.2014, 15:28  [ТС] 4
Цитата Сообщение от _Ivana Посмотреть сообщение
Буквально вчера столкнулся с той же проблемой. Совершенно не знаю и не понимаю монад, но те пару раз, когда я с ними связывался, вроде помогало
Такая же фигня Но на этот раз не прокатило:
Couldn't match expected type `Command' with actual type `()'
In the first argument of `return', namely `()'
In the expression: return ()
In an equation for `trajectory2GCode':
trajectory2GCode [] _ = return ()
Цитата Сообщение от Araneo Посмотреть сообщение
А записать пустой список не получиться?
Не. Тоже не прокатило. Пришлось сделать так, как сделано у меня. Но как-то это на костыль смахивает: создать специльный нульарный конструктор, чтобы Writerу было что писать.
0
Эксперт по математике/физике
4156 / 2059 / 424
Регистрация: 19.07.2009
Сообщений: 3,117
Записей в блоге: 24
04.12.2014, 16:45 5
Во-первых, можно изменить тип CNC. Зачем Вам возвращать Command? Почему не newtype CNC = Writer [Command] ()? Только тогда нужно все строки заканчивать фразой return (). Зато можно описывать действия, которые не возвращают никакой команды, но (возможно) содержат в себе некоторые команды, то есть не нужен будет Null.

Во-вторых, посмотрите на функцию sequence_ :: [Writer [Command] a] -> Writer [Command] ()
Вы можете выделить функцию segment2Code :: Double -> TSegment -> CNC и написать trajectory2Code xs z = sequence $ map (segment2Code z) xs
Это избавит Вас от повторяющегося каркаса trajectory2Code (... : xs) z = do ...; trajectory2Code xs и вопросом, что делать в конце процесса.
2
4265 / 2806 / 410
Регистрация: 01.06.2013
Сообщений: 5,892
Записей в блоге: 9
04.12.2014, 18:02 6
type CNC = Writer [Command] () , но никакие строки не надо заканчивать return (), кроме последней
Haskell
1
trajectory2GCode [] _ = return ()
Функцию write f = ... удалить и использовать tell.
2
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 411
Записей в блоге: 1
04.12.2014, 21:55  [ТС] 7
Что-то не соображу, что он пытается мне сказать :-(

Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
data Position = 
        X Double
    |   Y Double
    |   Z Double
    |   I Double
    |   J Double
 
-- команды
data Command =
        G0 [Position]
 
type CNC = Writer [Command] ()
 
g0 :: [Position] -> CNC
g0 l = tell $ G0 l
 
export f = 
    mapM_ (putStrLn.show) y
    where (_, y) = runWriter f
 
ff = do
    g0 [X 12]
 
main = do
    putStrLn $ show ff
/home/aaleksander/dev/Haskell/Hs2gcode/src/Export.hs:4:8:
Couldn't match type `[Command]' with `Command'
When using functional dependencies to combine
MonadWriter w (WriterT w m),
arising from the dependency `m -> w'
in the instance declaration in `Control.Monad.Writer.Class'
MonadWriter
Command (WriterT [Command] Data.Functor.Identity.Identity),
arising from a use of `tell'
at /home/aaleksander/dev/Haskell/Hs2gcode/src/Export.hs:15:8-11
In the expression: tell
In the expression: tell $ G0 l
Добавлено через 24 минуты
Цитата Сообщение от Mysterious Light Посмотреть сообщение
Во-вторых, посмотрите на функцию sequence_ :: [Writer [Command] a] -> Writer [Command] ()
К сожалению не очень подходит: чтобы выполнить некоторые сегменты, нужно знать последующие.
Мне пока мой код не очень нравится. Например, передаю в trajectory2GCode дополнительную переменную только ради одного сегмента (TJump, и не факт что он там есть). Это не очень правильно. В идеале, надо бы переписать так, чтобы записывая очередной раз во Writer, я мог обратиться к его последнему значению, где будет 3Д-координата, и сделать какой-нибудь маневр.
Например, в случае с TJump, нужно посмотреть, на какой глубине находимся, подняться на безопасную высоту, передвинуть и опустить на ту же самую глубину.

P.S. Что-то как-то сумбурно, завтра подробнее распишу, если интересно.
0
4265 / 2806 / 410
Регистрация: 01.06.2013
Сообщений: 5,892
Записей в блоге: 9
04.12.2014, 22:04 8
Цитата Сообщение от aaleksander Посмотреть сообщение
Что-то не соображу, что он пытается мне сказать :-(
Он пытается сказать что между конструкторами должны быть запятые, функция export не используется, а ff используется неправильно, что не обязательно всегда использовать where и пр. и пр.
0
111 / 85 / 21
Регистрация: 06.06.2011
Сообщений: 411
Записей в блоге: 1
04.12.2014, 22:20  [ТС] 9
Что-то я замудрули, пытаясь вырезать лишнее и оставить нужное.
Вот синтетический пример, который не работает, но вроде как должен:
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Control.Monad.Writer
 
newtype CNC = Writer [Int]
 
f :: CNC
f = do
    tell 1
    tell 2
 
export :: CNC -> IO ()
export f = 
    mapM_ (putStrLn.show) y
    where (_, y) = runWriter f
 
main = do
    export f
    putStrLn "test"
А вот тоже самое, которое работает, но не разрешает "ничего не писать".
Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Control.Monad.Writer
 
type CNC = Writer [Int] (Int)
 
f :: CNC
f = do
    writer (1, [1])
    writer (1, [2])
 
export :: CNC -> IO ()
export f = 
    mapM_ (putStrLn.show) y
    where (_, y) = runWriter f
 
main = do
    export f
    putStrLn "test"
0
Эксперт по математике/физике
4156 / 2059 / 424
Регистрация: 19.07.2009
Сообщений: 3,117
Записей в блоге: 24
04.12.2014, 22:27 10
Лучший ответ Сообщение было отмечено aaleksander как решение

Решение

Haskell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import Control.Monad.Writer
 
type CNC = Writer [Int] ()
 
f :: CNC
f = do
    tell [1]
    tell [2]
    tell []
    tell [3]
    return ()
    tell [5]
 
export :: CNC -> IO ()
export f = 
    mapM_ (putStrLn.show) y
    where (_, y) = runWriter f
 
main = do
    export f
    putStrLn "test"
2
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
04.12.2014, 22:27

Как сделать чтобы при вводе 0 и других символов, кроме цифр ничего не вводилось?
Подскажите пожалуйста.

Как сделать так, чтобы нельзя было ничего делать с главным фреймом, пока открыт диалог?
Доброго дня. Я новичок в программировании. Пишу крестики-нолики. Допустим, игрок выигрывает,...

Как на главной вьюхе сделать кнопку которая автоматом делала бы заказ
Короче такой трабл, есть MVC приложение. Есть главная страница в которой выводятся данные с...

Как сделать чтобы при нажатии "Ctrl+Alt+Delete" ничего не происходило.
Как сделать чтобы при нажатии 'Ctrl+Alt+Delete' ничего не происходило.


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru