2016-04-18 5 views
0

Я пытался упростить небольшую программу, используя System.Console.Terminfo. Я получил до mappend ing несколько Capability вместе, но всякий раз, когда мне нужно их оценить, я должен использовать getCapability, а затем использовать case для соответствия шаблону полученному Maybe. Образец всегда один и тот жеКак правильно использовать способ использования Terminfo. Отвечают ли монады-трансформаторы?

Just ... -> runTermOutput ... 
Nothing -> return() 

поэтому я считаю, что должен быть лучший способ сделать это. Мне кажется, что сопоставление шаблонов заменяет Maybe на IO, поэтому я подумал, что это могут быть для монадных трансформаторов. Глядя на Capability определение,

> :i Capability 
newtype Capability a 
    = System.Console.Terminfo.Base.Capability (Terminal 
              -> IO (Maybe a)) 
... 

это выглядит похоже на MaybeT пример я нашел здесь, на StackOverflow, но тот факт, что это функция бросает меня. (Кроме того, я не могу утверждать, что понимаю монадные трансформаторы после прочтения только одного примера.)

Я нахожусь на правильном пути? Есть ли другой шаблон, который может помочь мне избежать написания этого case снова и снова?

Вот getCapability Тип:

> :i getCapability 
getCapability :: Terminal -> Capability a -> Maybe a 
... 
+0

Это может помочь, если вы могли бы разместить больший пример шаблона вам не нравится в контекст. Но интересно, посмотрел ли ты на то, что предлагает вам экземпляр «Монады»? '(>> =) :: Способность a -> (a -> Способность b) -> Способность b' – jberryman

+0

@jberryman: Bind не получает меня в этом случае, поскольку я пытаюсь перейти от« Способности a - > IO() ', так что' main' может его выполнить. Однако, рассматривая этот вопрос, я думаю, что моя фактическая проблема заключается в том, что 'runTermOutput :: Terminal -> TermOutput -> IO()' не использует 'Capability'. Наличие некоторой функции 'runCapability :: Terminal -> Capability TermOutput -> IO()', вероятно, избавит меня от повторения кода. Хм, я думаю, этот вопрос слишком специфичен для StackOverflow. Может/если оно будет изменено на более общее, «Как использовать Terminfo?» – user2063685

+0

@ user2063685 Есть ли причина, по которой вы не можете написать такую ​​функцию? например '\ t c -> возможно (return()) (\ x -> runTermOutput ...). getCapability t c' - просто определите его везде, где хотите, и используйте его. Трансформаторы Monad не помогут вам здесь - вы можете использовать трансформатор «MaybeT IO», но если вы не используете логику «Maybe» в другом месте, это не даст вам ничего, кроме простого определения функции, которую вы хотите. Вопрос вроде «Как использовать Terminfo?» вероятно, будет слишком широким. – user2407038

ответ

0

Из того, что я понимаю, интерфейс Terminfo Capability означает, что трансформаторы монады не являются ответом.

Как user2407038 предложил, то case шаблон можно избежать с помощью функции,

\t -> maybe (return()) (runTermOutput t) . (getCapability t) 
    :: Terminal -> Capability TermOutput -> IO() 
1
mapM :: (Monad m, Traversable t) => (a -> m b) -> t a -> m (t b) 

специализируется не только

mapM :: (a -> IO b) -> [a] -> IO [b] 

, но и

mapM :: (a -> IO b) -> Maybe a -> IO (Maybe b) 

. То же самое касается mapM_ и for и for_ и traverse и traverse_.

+0

'Capability' не является экземпляром' Traversable'. Как я могу определить экземпляр? – user2063685

+0

Я имел в виду, что вы используете это вместо совпадения. Hmm * rereads post and discussion * Почему у вас есть более одного места, где вы хотите конвертировать возможности в IO? (Если это только последующие строки в одной и той же основной части, где каждый шаг зависит от предыдущего результата, вы действительно можете использовать bind) – Gurkenglas

+0

'Capability' фактически поддерживает' mappend', так что это то, что я использовал, чтобы объединить его. Я думаю, ваше предложение эквивалентно. – user2063685

 Смежные вопросы

  • Нет связанных вопросов^_^