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 创建typeclass时,无法从上下文推断_Haskell_Typeclass - Fatal编程技术网

Haskell 创建typeclass时,无法从上下文推断

Haskell 创建typeclass时,无法从上下文推断,haskell,typeclass,Haskell,Typeclass,我正在使用库,我想自动将结果映射到错误代码中。仆人需要类型:或(Int,String)a 例如,如果我有一个类型为:IO(可能是User)的模型函数。我想把它转到(404,“未找到”)上,如果它在那里,则转到用户 为了做到这一点,我正在写一个typeclass class Servile a where toStatus :: ToJSON val => a -> Either (Int, String) val instance ToJSON a => Servil

我正在使用库,我想自动将结果映射到错误代码中。仆人需要类型:
或(Int,String)a

例如,如果我有一个类型为:
IO(可能是User)
的模型函数。我想把它转到
(404,“未找到”)
上,如果它在那里,则转到
用户

为了做到这一点,我正在写一个typeclass

class Servile a where
    toStatus :: ToJSON val => a -> Either (Int, String) val

instance ToJSON a => Servile (Maybe a) where
    toStatus Nothing  = Left (404, "Not Found")
    toStatus (Just a) = Right a
我还想写其他实例,但这一个给了我一个错误:

Could not deduce (a ~ val)
from the context (ToJSON a)
  bound by the instance declaration at Serials/Api.hs:90:10-38
or from (ToJSON val)
  bound by the type signature for
             toStatus :: ToJSON val => Maybe a -> Either (Int, String) val
  at Serials/Api.hs:91:5-12
  ‘a’ is a rigid type variable bound by
      the instance declaration at Serials/Api.hs:90:10
  ‘val’ is a rigid type variable bound by
        the type signature for
          toStatus :: ToJSON val => Maybe a -> Either (Int, String) val
        at Serials/Api.hs:91:5
Relevant bindings include
  a :: a (bound at Serials/Api.hs:92:20)
  toStatus :: Maybe a -> Either (Int, String) val
    (bound at Serials/Api.hs:91:5)
In the first argument of ‘Right’, namely ‘a’
In the expression: Right a
做这件事的正确方法是什么?

我跳到哈斯克尔身上,因为我没有很好地表达这个问题。问题是,它不能在任何
a
上变化,以生成这样的
val
。这也证明了
ToJSON
与这个问题无关

这是有效的:请注意,我将
toStatus
更改为
aval
,而不是
a
,并将实例删除类型变量

class ToStatus a where
    toStatus :: a val -> Either (Int, String) val

instance ToStatus Maybe where
    toStatus Nothing  = Left (404, "Not Found")
    toStatus (Just v) = Right v

instance Show a => ToStatus (Either a) where
    toStatus (Left a) = Left (500, "Server Error: " <> show a)
    toStatus (Right v) = Right v
类ToStatus a,其中
toStatus::a val->or(Int,String)val
比如托斯塔斯,可能在哪里
toStatus Nothing=左侧(404,“未找到”)
toStatus(仅v)=右v
实例Show a=>ToStatus(或a),其中
toStatus(左a)=左(500,“服务器错误:”显示a)
toStatus(右v)=右v

如果您想使用一些非参数化类型,另一种解决方案是使用
TypeFamilies

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleInstances #-}
module Temp where
import Data.Monoid

class ToStatus a where
  type Val a
  toStatus :: a -> Either (Int, String) (Val a)

instance ToStatus (Maybe a) where
  type Val (Maybe a) = a 
  toStatus Nothing  = Left (404, "Not Found")
  toStatus (Just v) = Right v

instance Show a => ToStatus (Either a b) where
  type Val (Either a b) = b 
  toStatus (Left e) = Left (500, "Server Error: " <> show e)
  toStatus (Right v) = Right v

instance ToStatus String where
  type Val String = ()
  toStatus "200 Success" = Right ()
  toStatus err = Left (500, err)
{-#语言类型族}
{-#语言灵活实例}
模块温度在哪里
导入数据.幺半群
托斯塔斯a班在哪里
Val a型
toStatus::a->other(Int,String)(Val a)
实例ToStatus(可能是a)在哪里
类型Val(可能是a)=a
toStatus Nothing=左侧(404,“未找到”)
toStatus(仅v)=右v
实例Show a=>ToStatus(a或b),其中
类型Val(a或b)=b
toStatus(左e)=左(500,“服务器错误:”显示e)
toStatus(右v)=右v
实例ToStatus字符串,其中
类型Val String=()
toStatus“200成功”=右()
toStatus err=左(500,err)

这不应该是
toStatus::ToJSON a=>a->other(Int,String)a
?那么可能是
toStatus::ToJSON a=>a->other(Int,String)JSON
?您希望如何将
a
转换成任何
ToJSON val=>val
?您当前的typeclass所说的是,您希望能够将一些实现了
Servile
a
转换为任何
ToJSON
类型。您可以通过使用
toStatus::a->任意一个(Int,String)值
来解决这个问题。直接返回
s意味着您不必担心模棱两可。在
Servile
实例中,您必须担心转换,但是如果您正在使用的已经实现了
ToJSON
,那么转换就足够简单了。如果您正在使用的东西没有实现
ToJSON
,那么您必须在您关心转换的地方处理它。完成后,您可以对所有内容调用
toStatus
,而不必担心重叠实例、不一致实例等。保持简单,只返回具体类型。@seanclakhes您想从
a
中提取
ToJSON val=>val
,但是,
a
没有限制这样说。
val
类型变量仅出现在
toStatus
的签名中,它当前必须来自任何地方。你能编辑你的问题来展示更多你想做的事情吗?哇,酷!有你推荐的类型系列介绍吗?@SeanClarkHess我很喜欢——也有