Личность Монад - Разница в поведении в Хаскеле? - PullRequest
0 голосов
/ 21 мая 2018

Я недавно играл с Монад в Хаскеле (все еще относительный новичок во всем этом).Я столкнулся с некоторым интересным поведением (или, по крайней мере, мне интересным) с Identity Monad.


Если я напишу следующую функцию:

let f = \x -> Identity 2 >>= \y -> x * y

а затем сделать :t я получу f :: Num b => Identity b -> Identity b.Из этого следует, что x является Identity (Num b).Я могу вызвать функцию с 6 и получаю результат 12.

Однако, если я попробую то же самое с Maybe, вот так:

let g = \x -> Just 2 >>= \y -> x * y

<interactive>:2096:5: error:
    • Non type-variable argument in the constraint: Num (Maybe b)
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        g :: forall b. Num (Maybe b) => Maybe b -> Maybe b

Поэтому мне нужно явно вернуть Maybe или использовать return.Вот и я так: let g = \x -> Just 2 >>= \y -> return $ x * y.

Все отлично работает.Однако потом мне стало интересно, что происходит с монадой Identity.

Сначала я попытался добавить явный тип возврата следующим образом:

let f = \x -> Identity 2 >>= \y -> Identity $ x * y

, а затемсделал :t снова, и я получил f :: Num b => b -> Identity b.Это то, чего я ожидал в первый раз.


Что заставило меня задуматься о том, как он мог обрабатывать x + y без Identity $, если он выводил x и y вбыть завернутым в Identity.Поэтому я попробовал следующее:

Identity 5 + Identity 6 с результатом 11

Identity 5 + 6 с результатом 11 снова

Тем не менее, я пытаюсь сделать то же самое с Maybe, вот так

Just 5 + Just 6

Just 5 + 6

Я получаюследующая ошибка:

<interactive>:2116:1: error:
    • Non type-variable argument in the constraint: Num (Maybe a)
      (Use FlexibleContexts to permit this)
    • When checking the inferred type
        it :: forall a. (Num (Maybe a), Num a) => Maybe a

Я пытался FlexibleContexts, но я только что получил следующую ошибку:

<interactive>:2134:1: error:
    • No instance for (Num (Maybe a0)) arising from a use of ‘it’
    • In the first argument of ‘print’, namely ‘it’
      In a stmt of an interactive GHCi command: print it

Мне было интересно, если кто-то может пролить немного света на почемуповедение монады Identity отличается от Maybe?

Также возможно ли использовать FlexibleContexts для получения того же поведения с монадой Maybe?Я пока не смог заставить его работать.

Большое спасибо за продвинутый уровень.

1 Ответ

0 голосов
/ 21 мая 2018

Это связано с тем, что Identity имеет экземпляр Num, а Maybe - нет (вы можете увидеть экземпляры типа, используя :i в GHCi или просмотрев в документации по Hackage ).

Итак, когда у вас есть \x -> Identity 2 >>= \y -> x * y, то * на самом деле является * из экземпляра Num для Identity a (где a сам является экземпляром Num, например,Int или Double и т. Д.).

Кроме того, числовые литералы в Haskell полиморфны: 5 :: Num a => a, поэтому они могут вести себя как любой экземпляр Num, а не ограничиваться конкретным экземпляром (например,Int или Double).Это то, что происходит, когда вы пытаетесь что-то вроде Identity 5 + 6.Предполагается, что 6 имеет тип Num a => Identity a, поскольку (+) :: Num a => a -> a -> a.

. Вы можете увидеть это более явно:

ghci> :t 5
5 :: Num p => p
ghci> 5 :: Identity Int
Identity 5
ghci> 5 :: Maybe Int

<interactive>:12:1: error:
    • No instance for (Num (Maybe Int)) arising from the literal ‘5’
    • In the expression: 5 :: Maybe Int
      In an equation for ‘it’: it = 5 :: Maybe Int
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...