сигнатура типа haskell для возврата конструктора типа - PullRequest
0 голосов
/ 20 апреля 2019

Можно ли дать сигнатуру типа для этой getConstructor функции? Функция работает, но я не могу найти способ написать тип возвращаемого значения.

module Main where

    data Letter a =
          A a
        | B a
        | C String
        deriving (Show)

    -- getConstructor :: String -> (a -> Letter ?) -- <== 
    getConstructor x
        | x == "a"  = A
        | x == "b"  = B
        | otherwise = C


    main = print $ theType
        where theType = (getConstructor "b") "its b!"

Основные принты B "its b!"

Ответы [ 2 ]

4 голосов
/ 20 апреля 2019

Давайте посмотрим:

getConstructor x
    | x == "a"  = A
    | x == "b"  = B
    | otherwise = C -- <= Let's inspect this line

Эта строка возвращает C :: String -> Letter a.Предыдущая строка возвращает B :: a -> Letter a.Эти типы должны быть равны, поэтому a ~ String.Следовательно, функция становится следующей:

getConstructor :: String -> (String -> Letter String)

Нет способа динамически выбирать тип во время выполнения с помощью такой функции, поскольку в Haskell все типы известны во время компиляции.Следовательно, он ограничен работой только на String s.

3 голосов
/ 20 апреля 2019

Я просто ввел ваш код в GHCi и попросил его сообщить мне тип:

Prelude> :{
Prelude|     data Letter a =
Prelude|           A a
Prelude|         | B a
Prelude|         | C String
Prelude|         deriving (Show)
Prelude| :}
Prelude> :{
Prelude|     getConstructor x
Prelude|         | x == "a"  = A
Prelude|         | x == "b"  = B
Prelude|         | otherwise = C
Prelude| :}
Prelude> :t getConstructor
getConstructor :: [Char] -> String -> Letter String

Это имеет смысл, потому что для этого требуется [Char] (он же String - это x аргумент) и возвращает один из A, B и C, которые являются конструкторами для Letter.Будучи конструкторами, они также являются функциями - в случае C тип явно String -> Letter a, тогда как A и B имеют тип a -> Letter a.Поскольку это все возможные возвращаемые значения getConstructor, они должны быть одного типа - единственный способ для этого - если a всегда равен String.Это дает нам тип getConstructor как String -> (String -> Letter String), что в точности соответствует тому, что GHCi говорит выше (с небольшим переписыванием).

...