2013-12-02 4 views
5

Я только что начал использовать netwire, и у меня возникли проблемы с самой базой.Haskell 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

Edit: Вот полное, компиляция, выполнение решения этой проблемы:

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 

Так что для Wire ы это:

(.) :: 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 

Edit: Даже лучше типа для forYeah

С an integer numeral (without a decimal point) is actually equivalent to an application of fromInteger to the value of the numeral as an Integer и 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 
0

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

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

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

0

Я просто спросил 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.

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