5

I have just started using netwire and I'm having trouble with the very basics.

The following code works fine for me:

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

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

But this does not:

main :: IO ()
main = testWire clockSession_ forYeah

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

fails with error:

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

So I changed it to:

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

which gives me the error:

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

Changing it to:

forYeah :: Wire s () Identity a String

Gives the following error:

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

Can someone explain why this happens and how I can fix my second code example?

4

3 回答 3

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

将类型更改yeahMonad m => Wire s e m a StringMonad m => (Wire s e m a)有一个Applicative实例,所以pure应该存在而不指定Wirein类型的第二个类型参数yeah().

注意:我不使用 netwire,也没有尝试编译它。我只查看了文档中的类型。

编辑:您可能还需要更改forYeah.

Wire还有一个Category实例:

Monad m => Category (Wire s e m)

Category.运算符具有以下类型:

(.) :: 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. 结合是的类型 of Monad m => Wire s e m a Stringfor 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 应用于作为 Integer 的数字的值,并且fromInteger :: (Num a) => Integer -> a,文字3实际上具有 type Num t => t。因此,我们可以选择的最佳类型可能是:

forYeah :: (Num t, HasTime t s, Monoid e, Monad m) => Wire s e m a String
于 2013-12-02T21:32:19.350 回答
0

当我将 forYeah 的类型更改为

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

如果你省略了 forYeah 的类型,它也可以工作。

于 2013-12-02T21:33:33.973 回答
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,我得到一个错误,说它不能与 匹配NominalDiffTimeInt但由于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约束中。由于您已将其排除在外,因此编译器将文字默认为3type Integer,但没​​有HasTime Integer sany的实例s

于 2013-12-02T21:48:46.183 回答