Haskell Netwire - Ошибки типа

Я только начал использовать NetWire, и у меня возникли проблемы с самими основами.

Следующий код прекрасно работает для меня:

main :: IO ()
main = testWire clockSession_ (for 3 . yeah)

yeah :: Monad m => Wire s () m a String
yeah = pure "yes"

Но это не так:

main :: IO ()
main = testWire clockSession_ forYeah

forYeah :: (Show b, Show e) => Wire s e Identity a b
forYeah = for 3 . yeah

не удается с ошибкой:

Could not deduce (b ~ [Char])
from the context (Show b, Show e)
bound by the type signature for
forYeah :: (Show b, Show e) => Wire s e Identity a b
  at /home/fiendfan1/workspace/Haskell/Haskell-OpenGL/src/Main.hs:12:12-54
  `b' is a rigid type variable bound by
      the type signature for
        forYeah :: (Show b, Show e) => Wire s e Identity a b
      at /home/fiendfan1/workspace/Haskell/Haskell-OpenGL/src/Main.hs:12:12
Expected type: Wire s e Identity a b
  Actual type: Wire s () Identity a String
In the second argument of `(.)', namely `yeah'
In the expression: for 3 . yeah
In an equation for `forYeah': forYeah = for 3 . yeah

Поэтому я изменил это на:

forYeah :: Show e => Wire s e Identity a String

что дает мне ошибку:

Could not deduce (e ~ ())
from the context (Show e)
  bound by the type signature for
             forYeah :: Show e => Wire s e Identity a String
  at /home/fiendfan1/workspace/Haskell/Haskell-OpenGL/src/Main.hs:12:12-49
  `e' is a rigid type variable bound by
      the type signature for
        forYeah :: Show e => Wire s e Identity a String
      at /home/fiendfan1/workspace/Haskell/Haskell-OpenGL/src/Main.hs:12:12
Expected type: Wire s e Identity a String
  Actual type: Wire s () Identity a String
In the second argument of `(.)', namely `yeah'
In the expression: for 3 . yeah
In an equation for `forYeah': forYeah = for 3 . yeah

Меняя это на:

forYeah :: Wire s () Identity a String

Выдает следующую ошибку:

No instance for (HasTime Integer s) arising from a use of `for'
Possible fix: add an instance declaration for (HasTime Integer s)
In the first argument of `(.)', namely `for 3'
In the expression: for 3 . yeah
In an equation for `forYeah': forYeah = for 3 . yeah

Может кто-нибудь объяснить, почему это происходит и как я могу исправить свой второй пример кода?

3 ответа

Решение

Изменить: Вот полное, компилирующее, работающее решение этой проблемы:

module Main (
    main
) where

import Prelude hiding ((.), id)
import qualified Prelude as Prelude
import Control.Wire
import Control.Wire.Interval

main :: IO ()
main = testWire clockSession_ (withoutErrors forYeah)

yeah :: Monad m => Wire s e m a String
yeah = pure "yes"

forYeah :: (Num t, HasTime t s, Monoid e, Monad m) => Wire s e m a String
forYeah = for 3 . yeah

-- This just is an easy way to specify to use () as the type for errors in testWire
withoutErrors :: Wire s () m a b -> Wire s () m a b 
withoutErrors = Prelude.id

Вот оригинальный ответ, который обсуждал, почему мы должны изменить тип yeah, а затем необходимые изменения в типе forYeah:

Изменить тип yeah в Monad m => Wire s e m a String, Monad m => (Wire s e m a) имеет Applicative например, так pure должен существовать без указания, что аргумент второго типа Wire в yeahтип (),

Примечание: я не использую netwire, и я не пробовал компилировать это. Я только посмотрел на типы в документации.

Изменить: Вам, вероятно, также необходимо изменить тип forYeah,

Wire также имеет Category пример:

Monad m => Category (Wire s e m)

Category"s . Оператор имеет следующий тип:

(.) :: cat b c -> cat a b -> cat a c

Таким образом, для Wires это:

(.) :: Monad m => Wire s e m b c -> Wire s e m a b -> Wire s e m a c

for имеет следующий тип:

for :: (HasTime t s, Monoid e) => t -> Wire s e m a a

Так for 3 будет иметь тип как (HasTime Int s, Monoid e) => Wire s e m a a, В сочетании с типом да Monad m => Wire s e m a String, for 3 . yeah будет иметь тип как

(HasTime Int s, Monoid e, Monad m) => Wire s e m a String

Таким образом, мы могли бы изменить тип forYeah чтобы:

forYeah :: (HasTime Int s, Monoid e, Monad m) => Wire s e m a String

Изменить: еще лучше тип для forYeah

Поскольку целое число (без десятичной точки) фактически эквивалентно применению fromInteger к значению числа в виде целого числа, и fromInteger :: (Num a) => Integer -> aБуквально 3 на самом деле имеет тип Num t => t, Поэтому лучший тип, который мы можем выбрать:

forYeah :: (Num t, HasTime t s, Monoid e, Monad m) => Wire s e m a String

Я просто спросил GHCi, какой тип был:

> :m Control.Wire
> :t for (3 :: Int) . pure "yes"
for 3 . pure "yes" :: (Monad m, HasTime Int s, Monoid e) => Wire s e m a [Char]
> :{
| let forYeah :: HasTime Int s => Wire s () Identity a String
|     forYeah = for 3 . pure "yes"
| :}
> :t forYeah
forYeah :: HasTime Int s => Wire s () Identity a String

Так что это работает. Тем не менее, когда спрашиваете тип testWire clockSession_ forYeahЯ получаю сообщение об ошибке, которое не может соответствовать NominalDiffTime с Int, но с тех пор NominalDiffTime также является примером Numдовольно просто изменить подпись:

> :{
| let forYeah :: HasTime NominalDiffTime s => Wire s () Identity a String
|     forYeah = for 3 . pure "yes"
| :}
> :t testWire clockSession_ forYeah
testWire clockSession_ forYeah :: (Applicative m, MonadIO m) => m c

Кажется, это сработает.

Кроме того, это сработало, когда я определил yeah отдельно как

yeah :: Monad m => Wire s () m a String
yeah = pure "yes"

forYeah :: HasTime t s => Wire s () Identity a String
forYeah = for 3 . yeah

Проблема, казалось, была в HasTime ограничение. Так как вы оставили его, компилятор по умолчанию выполнил 3 к типу Integer, но нет экземпляра для HasTime Integer s для любого s,

Это работает для меня, когда я меняю тип forYeah на

forYeah::Wire (Timed NominalDiffTime ()) () Identity a String

Это также работает, если вы пропустите тип forYeah.

Другие вопросы по тегам