Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 哈斯克尔:如何修复;类型变量“ambigous”;编译器错误?_Haskell_Reflex - Fatal编程技术网

Haskell 哈斯克尔:如何修复;类型变量“ambigous”;编译器错误?

Haskell 哈斯克尔:如何修复;类型变量“ambigous”;编译器错误?,haskell,reflex,Haskell,Reflex,我使用的是GHCJSi,版本0.2.0-7.10.3:和Reflection dom库版本0-4(来自)。我没有使用Hackage中的reflect-dom-0.3 以下Haskell程序未使用Reflect-dom-0.4编译: {-# LANGUAGE RecursiveDo, ScopedTypeVariables, DeriveGeneric, OverloadedStrings #-} import Reflex import Reflex.Dom import Data.Aeson

我使用的是GHCJSi,版本0.2.0-7.10.3:和Reflection dom库版本0-4(来自)。我没有使用Hackage中的reflect-dom-0.3

以下Haskell程序未使用Reflect-dom-0.4编译:

{-# LANGUAGE RecursiveDo, ScopedTypeVariables, DeriveGeneric, OverloadedStrings #-}
import Reflex
import Reflex.Dom
import Data.Aeson
import GHC.Generics
import qualified Data.Text as T
data Apod = Apod { copyright :: T.Text
                 , date :: T.Text
                 , explanation :: T.Text
                 , hdurl :: T.Text
                 , media_type :: T.Text
                 , service_version :: T.Text
                 , title :: T.Text
                 , url :: T.Text
                 } deriving (Generic, Show)
instance FromJSON Apod
main :: IO ()
main = do
  mainWidget $ el "div" $ do
    buttonEvent <- button "GET"
    let url = "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"
    let defaultReq = xhrRequest "GET" url def  
    asyncEvent <- performRequestAsync (tag (constant defaultReq) buttonEvent)
    let rspApod = fmapMaybe (\r -> decodeXhrResponse r) asyncEvent
    return ()
我内联反射dom库函数
decodeXhrResponse
(以及
decodeText
)。我将类型签名
从JSON a=>XhrResponse->maybea
更改为没有类型变量的签名
XhrResponse->maybea Apod
。然后程序编译成功

{-# LANGUAGE RecursiveDo, ScopedTypeVariables, DeriveGeneric, OverloadedStrings #-}
import Reflex
import Reflex.Dom hiding (decodeXhrResponse, decodeText)
-- import Reflex.Dom
import Data.Aeson
import GHC.Generics
import qualified Data.Text as T
import Control.Monad
import qualified Data.ByteString.Lazy as BL
import Data.Text.Encoding
data Apod = Apod { copyright :: T.Text
                 , date :: T.Text
                 , explanation :: T.Text
                 , hdurl :: T.Text
                 , media_type :: T.Text
                 , service_version :: T.Text
                 , title :: T.Text
                 , url :: T.Text
                 } deriving (Generic, Show)
instance FromJSON Apod
main :: IO ()
main = do
  mainWidget $ el "div" $ do
    buttonEvent <- button "GET"
    let nasa = "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"
    let defaultReq = xhrRequest "GET" nasa def 
    asyncEvent <- performRequestAsync (tag (constant defaultReq) buttonEvent)
    let rspApod :: Event Spider Apod = fmapMaybe (\r -> decodeXhrResponse r) asyncEvent
    return ()
-- Inlined and changed library function:
-- decodeXhrResponse :: FromJSON a => XhrResponse -> Maybe a
decodeXhrResponse :: XhrResponse -> Maybe Apod
decodeXhrResponse = join . fmap decodeText . _xhrResponse_responseText
-- Inlined and changed library function:
-- decodeText :: FromJSON a => T.Text -> Maybe a
decodeText :: T.Text -> Maybe Apod
decodeText = decode . BL.fromStrict . encodeUtf8
{-#语言递归DO,ScopedTypeVariables,DeriveGeneric,重载字符串#-}
输入反射
导入reflection.Dom隐藏(decodeXhrResponse,decodeText)
--导入反射.Dom
导入数据.Aeson
进口GHC.仿制药
导入符合条件的数据。文本为T
进口管制
将限定数据.ByteString.Lazy导入为BL
导入Data.Text.Encoding
数据Apod=Apod{版权::T.文本
,日期::T.Text
,解释::T.文本
,hdurl::T.Text
,媒体类型::T.文本
,服务版本::T.文本
,title::T.Text
,url::T.Text
}派生(通用、显示)
来自JSON Apod的实例
main::IO()
main=do
mainWidget$el“div”$do
按钮无Xhr响应->可能是
解码XhrResponse::XhrResponse->可能是Apod
decodeXhrResponse=加入。fmap解码文本_xhrResponse\u responseText
--内联和更改的库函数:
--decodeText::FromJSON a=>T.Text->可能是a
解码文本::T.文本->可能是Apod
解码文本=解码。基本法。编码UTF8
我试图为rspApod添加一个作用域类型变量,如
rspApod::Event t Apod
rspApod::Event Spider Apod
,但没有帮助

问题:

如何更改第一个程序才能成功编译?(内联和更改库函数是一个非常糟糕的技巧!)


为什么编译器没有找到并使用数据类型
Apod
FromJSON
实例?

因此函数的原始签名是

decodeXhrResponse::FromJSON a=>XhrResponse->Maybe a

因此,在使用时,编译器需要为给定的
a
从JSON中找到
实例。在您的例子中,
a
Apod
,因此编译器应该对
Apod
FromJSON
实例进行微调。在您的代码中,编译器无法知道这是您的意图。这是解析时的常见问题,需要告诉编译器目标类型应该是什么

现在您可能会争辩说,它应该能够通过周围的代码(如
asyncEvent
)来确定目标类型,但这不是出于某种原因。可能是周围的代码也是通用的。考虑下面的场景:

main=print$read x

编译器如何知道读取
x
的目标类型

read::reada=>String->a
显然,这不会通知它目标

print::Show a=>a->IO()
这只是断言
a
必须有一个
Show
实例

a
太泛型,无法解析,我们需要一个具体类型

因此,当内联函数并将类型签名更改为包含
Apod
时,您为编译器提供了所需的信息,让编译器知道从JSON
实例中查找什么内容

下面是我如何解决这个问题的:

main :: IO ()
main = do
  mainWidget $ el "div" $ do
    buttonEvent <- button "GET"
    let url = "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"
    let defaultReq = xhrRequest "GET" url def  
    asyncEvent <- performRequestAsync (tag (constant defaultReq) buttonEvent)
    let rspApod = fmapMaybe (\r -> decodeXhrResponse r :: Maybe Apod) asyncEvent
    return ()
main::IO()
main=do
mainWidget$el“div”$do

buttonEvent因此函数的原始签名是

decodeXhrResponse::FromJSON a=>XhrResponse->Maybe a

因此,在使用时,编译器需要为给定的
a
从JSON
中找到
实例。在您的例子中,
a
Apod
,因此编译器应该对
Apod
FromJSON
实例进行微调。在您的代码中,编译器无法知道这是您的意图。这是解析时的常见问题,需要告诉编译器目标类型应该是什么

现在您可能会争辩说,它应该能够通过周围的代码(如
asyncEvent
)来确定目标类型,但这不是出于某种原因。可能是周围的代码也是通用的。考虑下面的场景:

main=print$read x

编译器如何知道读取
x
的目标类型

read::reada=>String->a
显然,这不会通知它目标

print::Show a=>a->IO()
这只是断言
a
必须有一个
Show
实例

a
太泛型,无法解析,我们需要一个具体类型

因此,当内联函数并将类型签名更改为包含
Apod
时,您为编译器提供了所需的信息,让编译器知道从JSON
实例中查找什么内容

下面是我如何解决这个问题的:

main :: IO ()
main = do
  mainWidget $ el "div" $ do
    buttonEvent <- button "GET"
    let url = "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY"
    let defaultReq = xhrRequest "GET" url def  
    asyncEvent <- performRequestAsync (tag (constant defaultReq) buttonEvent)
    let rspApod = fmapMaybe (\r -> decodeXhrResponse r :: Maybe Apod) asyncEvent
    return ()
main::IO()
main=do
mainWidget$el“div”$do

按钮事件
(\r->decodexhresponse r)
~>
decodexhresponse
您的原始程序不明确。仅仅添加一个类型签名
decodexhresponse r::Maybe Apod
@Reid:谢谢,但是更改为
let rspApod=fmapMaybe(\r->decodexhresponse r::Maybe Apod)asyncEvent
并不能解决问题:为相同的
提供了一个
实例。不幸的是…这似乎很难相信…在添加类型批注后,在上面发布完整错误。
(\r->decodexhresponse r)
~>
decodexhresponse
您的原始程序不明确。只添加一个类型签名如何
decodeXhrResponse r::Maybe