Haskell Netwire - 输入错误

时间:2013-12-02 20:53:49

标签: haskell functional-programming frp 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 个答案:

答案 0 :(得分: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 StringMonad m => (Wire s e m a)Applicative个实例,因此pure应该存在而不指定Wire类型中yeah的第二个类型参数为()

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

修改:您可能还需要更改forYeah的类型。

Wire还有Category个实例:

Monad m => Category (Wire s e m)

Category的{​​{1}}运算符具有以下类型:

.

因此对于(.) :: 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。结合yeah的(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

类型

an integer numeral (without a decimal point) is actually equivalent to an application of fromInteger to the value of the numeral as an IntegerforYeah起,文字fromInteger :: (Num a) => Integer -> a实际上有3类型。因此,我们可以选择的最佳类型可能是:

Num t => t

答案 1 :(得分:0)

当我将forYeah的类型改为

时,它对我有用
forYeah::Wire (Timed NominalDiffTime ()) () Identity a String

如果省略forYeah的类型,它也有效。

答案 2 :(得分: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的实例1}},只需更改签名即可:

> :{
| 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的实例。