String을 타입 클래스의 인스턴스로 만들 수없는 이유는 무엇입니까?
주어진 :
data Foo =
FooString String
…
class Fooable a where --(is this a good way to name this?)
toFoo :: a -> Foo
다음 String
의 인스턴스 를 만들고 싶습니다 Fooable
.
instance Fooable String where
toFoo = FooString
GHC는 다음과 같이 불평합니다.
Illegal instance declaration for `Fooable String'
(All instance types must be of the form (T t1 ... tn)
where T is not a synonym.
Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Fooable String'
대신 사용하면 [Char]
:
instance Fooable [Char] where
toFoo = FooString
GHC는 다음과 같이 불평합니다.
Illegal instance declaration for `Fooable [Char]'
(All instance types must be of the form (T a1 ... an)
where a1 ... an are type *variables*,
and each type variable appears at most once in the instance head.
Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Fooable [Char]'
질문 :
- String 및 typeclass의 인스턴스를 만들 수없는 이유는 무엇입니까?
- 추가 플래그를 추가하면 GHC가 기꺼이이 문제를 해결해 줄 것 같습니다. 이것이 좋은 생각입니까?
이것은 String
형식 [Char]
에 대한 형식 생성자의 응용 프로그램 인에 대한 형식 별칭 일 뿐이 므로 []
형식 Char
이 될 수 있기 때문입니다 ([] Char)
. 형식 변수가 아니기 (T a1 .. an)
때문에 형식 Char
이 아닙니다.
이 제한의 이유는 중복 인스턴스를 방지하기위한 것입니다. 예를 들어,을 가지고 있는데 instance Fooable [Char]
나중에 누군가가 와서 instance Fooable [a]
. 이제 컴파일러는 사용하려는 것을 파악할 수 없으며 오류가 발생합니다.
를 사용 -XFlexibleInstances
하면 기본적으로 그러한 인스턴스를 정의하지 않겠다고 컴파일러에 약속하게됩니다.
수행하려는 작업에 따라 래퍼를 정의하는 것이 더 나을 수 있습니다.
newtype Wrapper = Wrapper String
instance Fooable Wrapper where
...
고전적인 Haskell98 유형 클래스의 두 가지 제한 사항에 직면 해 있습니다.
- 인스턴스에서 유형 동의어를 허용하지 않습니다.
- 차례로 유형 변수를 포함하지 않는 중첩 유형을 허용하지 않습니다.
이러한 번거로운 제한은 두 가지 언어 확장으로 해제됩니다.
-XTypeSynonymInstances
형식 동의어 (예 : String
for [Char]
) 를 사용할 수 있습니다 .
-XFlexibleInstances
which lift the restrictions on instance types being of the form T a b ..
where the parameters are type variables. The -XFlexibleInstances
flag allows the head of the instance declaration to mention arbitrary nested types.
Note that lifting these restrictions can sometimes lead to overlapping instances, at which point, an additional language extension might be needed to resolve the ambiguity, allowing GHC to pick an instance for you.
References::
- Relaxed rules for the instance head, in the GHC User's Guide.
FlexibleInstances are not a good answer in most cases. Better alternatives are wrapping the String in a newtype or introduce a helper class like so:
class Element a where
listToFoo :: [a] -> Foo
instance Element Char where
listToFoo = FooString
instance Element a => Fooable [a] where
toFoo = listToFoo
See also: http://www.haskell.org/haskellwiki/List_instance
Adding to these answers, if you are not comfortable with lifting the restrictions, there may be cases where it could make sense to wrap your String in a newtype, which can be an instance of a class. The tradeoff would be potential ugliness, having to wrap and unwrap in your code.
참고URL : https://stackoverflow.com/questions/5941701/why-can-i-not-make-string-an-instance-of-a-typeclass
'development' 카테고리의 다른 글
.NET에서 SSIS 패키지를 실행하는 방법은 무엇입니까? (0) | 2020.09.19 |
---|---|
Python에 Rake에 해당하는 것이 있습니까? (0) | 2020.09.19 |
Dijkstra의 알고리즘이 감소 키를 사용하는 이유는 무엇입니까? (0) | 2020.09.19 |
자바 스크립트 예외 스택 추적 (0) | 2020.09.19 |
File.exists ()는 파일이있을 때 false를 반환합니다. (0) | 2020.09.19 |