문제

이 코드:

type family Id obj :: *
type instance Id Box = Int

나는 그것을 만들고 싶은 그래서 나는 항상 얻을 수 있습 Int 에서의 Id 를 입력 가족입니다.인식 전환이 필요합니다.

나는 면을 만들기 클래스 작동:

class IdToInt a where
  idToInt :: Id a -> Int

instance IdToInt Box where
  idToInt s = s

그리고 실제로 컴파일.하지만하려고 하는데 그것을 사용:

testFunc :: Id a -> Int
testFunc x = idToInt x

나는 오류가:

src/Snowfall/Spatial.hs:29:22:
Couldn't match type `Id a0' with `Id a'
NB: `Id' is a type function, and may not be injective
In the first argument of `idToInt', namely `x'
In the expression: idToInt x
In an equation for `testFunc': testFunc x = idToInt x

그래서,어떻게 만들 수 있습니 변환 유형에 대한 가족 Id 을 얻을 Int?

에 따라 대답하여 ehird 가는 다음이지만 그것은 작동하지 않거나:

class IdStuff a where
  type Id a :: *
  idToInt :: Id a -> Int

instance IdStuff Box where
  type Id Box = Int
  idToInt s = s

testFunc :: (IdStuff a) => Id a -> Int
testFunc x = idToInt x

그것은 오류가:

src/Snowfall/Spatial.hs:45:22:
Could not deduce (Id a0 ~ Id a)
from the context (IdStuff a)
  bound by the type signature for
             testFunc :: IdStuff a => Id a -> Int
  at src/Snowfall/Spatial.hs:45:1-22
NB: `Id' is a type function, and may not be injective
In the first argument of `idToInt', namely `x'
In the expression: idToInt x
In an equation for `testFunc': testFunc x = idToInt x
도움이 되었습니까?

해결책

다른 사람들이 지적으로,문제는 컴파일러 알아낼 수 없습니다 a 사용합니다.데이터 가족은 하나의 솔루션이지만,대체는 때때로 쉽게 작동하는 형식을 사용하려면 증인이다.

변경 클래스

class IdToInt a where
  idToInt :: a -> Id a -> Int

instance IdToInt Box where
  idToInt _ s = s

-- if you use this a lot, it's sometimes useful to create type witnesses to use
box = undefined :: Box

-- you can use it like
idToInt box someId

-- or
idToInt someBox (getId someBox)

질문에 응답할 필요가 있는 어떠한어 Id, 가 단 하나의 유형 a 그것은 나타나야 합니까?즉,거기에 하나를 하나 사이의 대응 as Id as?그렇다면,데이터 가족하는 올바른 접근 방식이다.하지 않을 경우,당신이 선호 할 수 있는 증거입니다.

다른 팁

당신은 할 수 없습니다.testFunc :: (IdToInt a) => Id a -> Int가 필요합니다.유형 가족이 열려 있으므로 누구도

를 선언 할 수 있습니다.
type instance Id Blah = ()
.

언제든지 전환 기능을 제공하지 않습니다.가장 좋은 방법은 유형 가족을 수업에 넣는 것입니다.

class HasId a where
  type Id a
  idToInt :: Id a -> Int

instance IdToInt Box where
  type Id Box = Int
  idToInt s = s
.

당신은 여전히 컨텍스트가 필요합니다.

할 수 없는 함수를 사용의 유형 IdToInt a => Id a -> Int 방법이 없기 때문에 어떤 종류의 결정 a 입니다.다음 예에서는 이 방법을 보여 줍니다.

type family Id a :: *
type instance Id () = Int
type instance Id Char = Int

class IdToInt a where idToInt :: Id a -> Int

instance IdToInt () where idToInt x = x + 1
instance IdToInt Char where idToInt x = x - 1

main = print $ idToInt 1

Id () = Id Char = Int, 의 유형 idToInt 위의 컨텍스트 Int -> Int, 은 다음과 같이 계산됩니다 Id () -> IntId Char -> Int.을 기억하는 오버로드 방법을 선택에 따라 형식입니다.모두 클래스의 인스턴스가 정의 idToInt 기능이 있는 형식 Int -> Int, 형식 검사 결정할 수 없는 한 사용합니다.

를 사용해야 합 데이터 가족을 대신의 유형이 가족,그리고 선언할 뉴스.

data family Id a :: *
newtype instance Id () = IdUnit Int
newtype instance Id Char = IdChar Int

와 뉴스 Id ()Id Char 은 모두 수 있지만,그들은 다른 유형이 있습니다.의 유형 Id 알 유형 검사에는 과부하 기능을 사용합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top