PureScript - 实例声明中出现的所有类型必须采用 T a_1 .. a_n 形式
PureScript - All types appearing in instance declarations must be of the form T a_1 .. a_n
考虑以下 PureScript 代码块,它定义了一个 showCustomer
类型 class。
module Main where
import Prelude
import Effect
import Effect.Console
class Show a where
show :: a -> String
type Customer = {
name :: String
}
customer :: Customer
customer = {
name : "Daniel Stern"
}
instance showCustomer :: Show Customer where
show a = "A customer"
但是此代码会产生以下错误,
Type class instance head is invalid due to use of type
( name :: String
)
All types appearing in instance declarations must be of the form T a_1 .. a_n, where each type a_i is of the same form, unless the type is fully determined by other type class arguments via functional dependencies.
问题:
如果传递给 show 的值是 Customer 类型,如何创建记录“客户”的 showCustomer 方法?
错误是什么意思?
type
只是一个类型同义词(就像 c 中的 typedef)。所以在编译过程中,
customer :: Customer
会变成
customer :: {name :: String}
所以你不能直接为type
创建实例。
如果你真的想创建实例,用newtype包装它然后为它创建一个实例。
newtype Customer = MkCustomer {
name :: String
}
customer :: Customer
customer = MkCustomer { name : "Daniel Stern"}
instance showCustomer :: Show Customer where
show (MkCustomer customer) = customer.name
虽然我不知道这个错误是什么意思
错误的字面意思是它所说的:实例头必须看起来像 T x y z
,而你的看起来像 { name :: String }
。
根本原因是 PureScript 不支持记录实例。对不起,运气不好。没办法。
如果您希望您的类型具有实例,它们必须是 newtype
或 data
,例如:
newtype Customer = Customer { name :: String }
但这有其自身的缺点:Customer
不再是记录,这意味着您不能再通过点访问其字段。你必须先打开类型才能得到包裹在里面的记录,然后你才能访问它的字段:
c = Customer { name: "John" }
doesntWork = c.name
works = let (Customer x) = c in x.name
-- also works:
getName :: Customer -> String
getName (Customer x) = x.name
还有一种(稍微)更短的方法可以使用 Newtype
class:
import Data.Newtype (class Newtype, unwrap)
newtype Customer = Customer { name :: String }
derive instance Newtype Customer _
c :: Customer
c = Customer { name: "John" }
john :: String
john = (unwrap c).name
考虑以下 PureScript 代码块,它定义了一个 showCustomer
类型 class。
module Main where
import Prelude
import Effect
import Effect.Console
class Show a where
show :: a -> String
type Customer = {
name :: String
}
customer :: Customer
customer = {
name : "Daniel Stern"
}
instance showCustomer :: Show Customer where
show a = "A customer"
但是此代码会产生以下错误,
Type class instance head is invalid due to use of type
( name :: String
)
All types appearing in instance declarations must be of the form T a_1 .. a_n, where each type a_i is of the same form, unless the type is fully determined by other type class arguments via functional dependencies.
问题:
如果传递给 show 的值是 Customer 类型,如何创建记录“客户”的 showCustomer 方法?
错误是什么意思?
type
只是一个类型同义词(就像 c 中的 typedef)。所以在编译过程中,
customer :: Customer
会变成
customer :: {name :: String}
所以你不能直接为type
创建实例。
如果你真的想创建实例,用newtype包装它然后为它创建一个实例。
newtype Customer = MkCustomer {
name :: String
}
customer :: Customer
customer = MkCustomer { name : "Daniel Stern"}
instance showCustomer :: Show Customer where
show (MkCustomer customer) = customer.name
虽然我不知道这个错误是什么意思
错误的字面意思是它所说的:实例头必须看起来像 T x y z
,而你的看起来像 { name :: String }
。
根本原因是 PureScript 不支持记录实例。对不起,运气不好。没办法。
如果您希望您的类型具有实例,它们必须是 newtype
或 data
,例如:
newtype Customer = Customer { name :: String }
但这有其自身的缺点:Customer
不再是记录,这意味着您不能再通过点访问其字段。你必须先打开类型才能得到包裹在里面的记录,然后你才能访问它的字段:
c = Customer { name: "John" }
doesntWork = c.name
works = let (Customer x) = c in x.name
-- also works:
getName :: Customer -> String
getName (Customer x) = x.name
还有一种(稍微)更短的方法可以使用 Newtype
class:
import Data.Newtype (class Newtype, unwrap)
newtype Customer = Customer { name :: String }
derive instance Newtype Customer _
c :: Customer
c = Customer { name: "John" }
john :: String
john = (unwrap c).name